use std::fs;
use std::path::{Path, PathBuf};
use rcgen::{BasicConstraints, CertificateParams, DnType, IsCa, KeyPair, KeyUsagePurpose};
use crate::error::{Error, Result};
#[derive(Debug, Clone)]
pub struct TestCerts {
pub ca_cert_file: PathBuf,
pub cert_file: PathBuf,
pub key_file: PathBuf,
}
pub fn generate_test_certs(dir: impl AsRef<Path>) -> Result<TestCerts> {
let dir = dir.as_ref();
fs::create_dir_all(dir).map_err(Error::Io)?;
let ca_key = KeyPair::generate().map_err(|e| Error::Tls(e.to_string()))?;
let mut ca_params =
CertificateParams::new(Vec::<String>::new()).map_err(|e| Error::Tls(e.to_string()))?;
ca_params
.distinguished_name
.push(DnType::CommonName, "Redis Test CA");
ca_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
ca_params.key_usages.push(KeyUsagePurpose::KeyCertSign);
ca_params.key_usages.push(KeyUsagePurpose::CrlSign);
let ca_cert = ca_params
.self_signed(&ca_key)
.map_err(|e| Error::Tls(e.to_string()))?;
let server_key = KeyPair::generate().map_err(|e| Error::Tls(e.to_string()))?;
let server_san = vec!["localhost".to_string(), "127.0.0.1".to_string()];
let mut server_params =
CertificateParams::new(server_san).map_err(|e| Error::Tls(e.to_string()))?;
server_params
.distinguished_name
.push(DnType::CommonName, "Redis Test Server");
let server_cert = server_params
.signed_by(&server_key, &ca_cert, &ca_key)
.map_err(|e| Error::Tls(e.to_string()))?;
let ca_cert_file = dir.join("ca.crt");
let cert_file = dir.join("server.crt");
let key_file = dir.join("server.key");
fs::write(&ca_cert_file, ca_cert.pem()).map_err(Error::Io)?;
fs::write(&cert_file, server_cert.pem()).map_err(Error::Io)?;
fs::write(&key_file, server_key.serialize_pem()).map_err(Error::Io)?;
Ok(TestCerts {
ca_cert_file,
cert_file,
key_file,
})
}