photoncloud-monorepo/deployer/crates/deployer-server/src/tls.rs

66 lines
2.4 KiB
Rust

use anyhow::{Context, Result};
use rcgen::{CertificateParams, DistinguishedName, DnType, KeyPair, SanType};
use std::net::IpAddr;
use std::path::Path;
pub fn issue_node_cert(
node_id: &str,
hostname: &str,
ip: &str,
ca_cert_path: Option<&str>,
ca_key_path: Option<&str>,
) -> Result<(String, String)> {
let mut dns_names = Vec::new();
if !node_id.trim().is_empty() {
dns_names.push(node_id.to_string());
}
if !hostname.trim().is_empty() && hostname != node_id {
dns_names.push(hostname.to_string());
}
if dns_names.is_empty() {
dns_names.push("photoncloud-node".to_string());
}
let mut params =
CertificateParams::new(dns_names).context("failed to create certificate params")?;
let mut distinguished_name = DistinguishedName::new();
if !node_id.trim().is_empty() {
distinguished_name.push(DnType::CommonName, node_id);
}
params.distinguished_name = distinguished_name;
if let Ok(ip_addr) = ip.parse::<IpAddr>() {
params.subject_alt_names.push(SanType::IpAddress(ip_addr));
}
let key_pair = KeyPair::generate().context("failed to generate TLS key pair")?;
if let (Some(ca_cert_path), Some(ca_key_path)) = (ca_cert_path, ca_key_path) {
let ca_cert_pem = std::fs::read_to_string(Path::new(ca_cert_path))
.with_context(|| format!("failed to read CA cert from {}", ca_cert_path))?;
let ca_key_pem = std::fs::read_to_string(Path::new(ca_key_path))
.with_context(|| format!("failed to read CA key from {}", ca_key_path))?;
let ca_key_pair =
KeyPair::from_pem(&ca_key_pem).context("failed to parse CA key pair from PEM")?;
let ca_params = CertificateParams::from_ca_cert_pem(&ca_cert_pem)
.context("failed to parse CA certificate")?;
let ca_cert = ca_params
.self_signed(&ca_key_pair)
.context("failed to build CA certificate for signing")?;
let cert = params
.signed_by(&key_pair, &ca_cert, &ca_key_pair)
.context("failed to sign node certificate")?;
let cert_pem = cert.pem();
let key_pem = key_pair.serialize_pem();
return Ok((cert_pem, key_pem));
}
let cert = params
.self_signed(&key_pair)
.context("failed to self-sign node certificate")?;
let cert_pem = cert.pem();
let key_pem = key_pair.serialize_pem();
Ok((cert_pem, key_pem))
}