use futures_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use rustls::ServerConfig;
use std::fs::File;
use std::io::{BufReader, Error, ErrorKind, Result};
use std::path::Path;
pub struct TlsConfig {
certs: Vec<CertificateDer<'static>>,
key: PrivateKeyDer<'static>,
}
impl TlsConfig {
pub fn from_pem(cert_path: impl AsRef<Path>, key_path: impl AsRef<Path>) -> Result<Self> {
let cert_file = File::open(cert_path)?;
let mut cert_reader = BufReader::new(cert_file);
let certs = rustls_pemfile::certs(&mut cert_reader).collect::<Result<Vec<_>>>()?;
if certs.is_empty() {
return Err(Error::new(
ErrorKind::InvalidInput,
"No certificates found in the file",
));
}
let key_file = File::open(key_path)?;
let mut key_reader = BufReader::new(key_file);
let key = rustls_pemfile::private_key(&mut key_reader)?
.ok_or_else(|| Error::new(ErrorKind::NotFound, "No private key found in the file"))?;
Ok(TlsConfig { certs, key })
}
pub fn from_raw(certs: Vec<Vec<u8>>, key: Vec<u8>) -> Self {
TlsConfig {
certs: certs.into_iter().map(CertificateDer::from).collect(),
key: PrivateKeyDer::Pkcs8(key.into()),
}
}
pub fn into_server_config(self) -> Result<ServerConfig> {
let mut config = ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(self.certs, self.key)
.map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
config.alpn_protocols = vec![b"http/1.1".to_vec()];
Ok(config)
}
}