use rcgen::{Certificate, CertificateParams, DnType, ExtendedKeyUsagePurpose, RcgenError};
use super::{Cert, CertParams, SerializedEntity};
pub struct EndEntity {
cert: Certificate,
}
impl Cert for EndEntity {
fn serialize(&self, signer: Option<&Certificate>) -> Result<SerializedEntity, RcgenError> {
let cert_pem = self.cert.serialize_pem_with_signer(signer.unwrap())?;
let key_pem = self.cert.serialize_private_key_pem();
Ok(SerializedEntity { cert_pem, key_pem })
}
fn cert(&self) -> &Certificate {
&self.cert
}
}
impl CertParams for EndEntityParams {
fn params(&self) -> &CertificateParams {
&self.params
}
}
pub struct EndEntityParams {
params: CertificateParams,
}
impl EndEntityParams {
pub fn new(params: CertificateParams) -> Self {
Self { params }
}
pub fn dns_name(mut self, name: &str) -> Self {
self.params
.subject_alt_names
.push(rcgen::SanType::DnsName(name.into()));
self.params
.distinguished_name
.push(DnType::CommonName, name);
self
}
pub fn client_auth(mut self) -> Self {
let usage = ExtendedKeyUsagePurpose::ClientAuth;
self.params.extended_key_usages.push(usage);
self
}
pub fn server_auth(mut self) -> Self {
let usage = ExtendedKeyUsagePurpose::ServerAuth;
self.params.extended_key_usages.push(usage);
self
}
pub fn build(self) -> Result<EndEntity, RcgenError> {
let cert = Certificate::from_params(self.params)?;
let cert = EndEntity { cert };
Ok(cert)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{cert::CertParams, BuildParams};
use rcgen::{DnValue, ExtendedKeyUsagePurpose, IsCa};
#[test]
fn client_auth_end_entity() {
let _ca = BuildParams::new().ca().build().unwrap();
let params = CertificateParams::default();
let cert = EndEntityParams::new(params).client_auth();
assert_eq!(cert.params().is_ca, IsCa::NoCa);
assert_eq!(
cert.params().extended_key_usages,
vec![ExtendedKeyUsagePurpose::ClientAuth]
);
}
#[test]
fn server_auth_end_entity() {
let _ca = BuildParams::new().ca().build().unwrap();
let params = CertificateParams::default();
let cert = EndEntityParams::new(params).server_auth();
assert_eq!(cert.params().is_ca, IsCa::NoCa);
assert_eq!(
cert.params().extended_key_usages,
vec![ExtendedKeyUsagePurpose::ServerAuth]
);
}
#[test]
fn dns_name_end_entity() {
let _ca = BuildParams::new().ca().build().unwrap();
let name = "unexpected.oomyoo.xyz";
let params = CertificateParams::default();
let cert = EndEntityParams::new(params).dns_name(name);
assert_eq!(
cert.params().subject_alt_names,
vec![rcgen::SanType::DnsName(name.into())]
);
assert_eq!(
cert.params()
.distinguished_name
.get(&DnType::CommonName)
.unwrap(),
&DnValue::from(name)
);
}
}