trz-gateway-common 0.2.0

Secure Proxy / Agents implementation in Rust
Documentation
use axum::http::StatusCode;
use nameth::NamedEnumValues as _;
use nameth::nameth;
use openssl::error::ErrorStack;
use openssl::x509::X509Builder;
use openssl::x509::X509NameRef;
use openssl::x509::X509Ref;
use openssl::x509::extension::AuthorityKeyIdentifier;
use openssl::x509::extension::SubjectKeyIdentifier;
use x509_parser::x509::X509Version;

use super::serial_number::SetSerialNumberError;
use super::serial_number::set_serial_number;
use super::time::SystemToAsn1TimeError;
use super::validity::Validity;
use super::validity::ValidityError;
use super::validity::set_validity;
use crate::http_error::IsHttpError;

pub fn set_common_fields(
    builder: &mut X509Builder,
    issuer_name: &X509NameRef,
    subject_name: &X509NameRef,
    validity: Validity,
) -> Result<(), SetCommonFieldsError> {
    builder
        .set_version(X509Version::V3.0 as i32)
        .map_err(SetCommonFieldsError::SetVersion)?;
    builder
        .set_subject_name(subject_name)
        .map_err(SetCommonFieldsError::SetSubject)?;
    builder
        .set_issuer_name(issuer_name)
        .map_err(SetCommonFieldsError::SetIssuer)?;
    set_validity(builder, validity.try_into()?)?;
    set_serial_number(builder)?;

    (|| {
        let skid = SubjectKeyIdentifier::new().build(&builder.x509v3_context(None, None))?;
        builder.append_extension(skid)?;
        Ok(())
    })()
    .map_err(SetCommonFieldsError::SubjectKeyIdentifier)?;

    Ok(())
}

#[nameth]
#[derive(thiserror::Error, Debug)]
pub enum SetCommonFieldsError {
    #[error("[{n}] Failed to set the X509 version: {0}", n = self.name())]
    SetVersion(ErrorStack),

    #[error("[{n}] Failed to set the subject name: {0}", n = self.name())]
    SetSubject(ErrorStack),

    #[error("[{n}] Failed to set the issuer name: {0}", n = self.name())]
    SetIssuer(ErrorStack),

    #[error("[{n}] {0}", n = self.name())]
    ConvertValidity(#[from] ValidityError<SystemToAsn1TimeError>),

    #[error("[{n}] {0}", n = self.name())]
    SetValidity(#[from] ValidityError<ErrorStack>),

    #[error("[{n}] {0}", n = self.name())]
    SetSerialNumber(#[from] SetSerialNumberError),

    #[error("[{n}] Failed to set SKID: {0}", n = self.name())]
    SubjectKeyIdentifier(ErrorStack),
}

impl IsHttpError for SetCommonFieldsError {
    fn status_code(&self) -> StatusCode {
        StatusCode::INTERNAL_SERVER_ERROR
    }
}

pub(super) fn set_akid(issuer: &X509Ref, builder: &mut X509Builder) -> Result<(), ErrorStack> {
    let akid = AuthorityKeyIdentifier::new()
        .issuer(true)
        .keyid(true)
        .build(&builder.x509v3_context(Some(issuer), None))?;
    builder.append_extension(akid)?;
    Ok(())
}