use time::OffsetDateTime;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MtlsClientIdentity {
pub serial: String,
pub fingerprint: String,
pub not_before: OffsetDateTime,
pub not_after: OffsetDateTime,
pub trusted_edge: bool,
}
impl MtlsClientIdentity {
#[must_use]
pub fn new(
serial: impl Into<String>,
fingerprint: impl Into<String>,
not_before: OffsetDateTime,
not_after: OffsetDateTime,
trusted_edge: bool,
) -> Self {
Self {
serial: serial.into(),
fingerprint: fingerprint.into(),
not_before,
not_after,
trusted_edge,
}
}
#[must_use]
pub fn validate_at(
&self,
now: OffsetDateTime,
revocation: &dyn MtlsRevocationLookup,
) -> MtlsClientIdentityStatus {
if !self.trusted_edge {
return MtlsClientIdentityStatus::UntrustedEdge;
}
if revocation.is_revoked(&self.serial, &self.fingerprint) {
return MtlsClientIdentityStatus::Revoked;
}
if now < self.not_before {
return MtlsClientIdentityStatus::NotYetValid;
}
if now >= self.not_after {
return MtlsClientIdentityStatus::Expired;
}
MtlsClientIdentityStatus::Valid
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MtlsClientIdentityStatus {
Valid,
UntrustedEdge,
NotYetValid,
Expired,
Revoked,
}
pub trait MtlsRevocationLookup {
fn is_revoked(&self, serial: &str, fingerprint: &str) -> bool;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NoMtlsRevocations;
impl MtlsRevocationLookup for NoMtlsRevocations {
fn is_revoked(&self, _serial: &str, _fingerprint: &str) -> bool {
false
}
}