feat(tls): add certificate expiry validation and self-signed warning
This commit is contained in:
@@ -28,6 +28,9 @@ pub fn build_server_config(
|
||||
let cert_bytes = std::fs::read(cert_path).context("read cert")?;
|
||||
let key_bytes = std::fs::read(key_path).context("read key")?;
|
||||
|
||||
// Validate certificate expiry and warn about self-signed certs.
|
||||
validate_certificate(&cert_bytes)?;
|
||||
|
||||
let cert_chain = vec![CertificateDer::from(cert_bytes)];
|
||||
let key = PrivateKeyDer::try_from(key_bytes).map_err(|_| anyhow::anyhow!("invalid key"))?;
|
||||
|
||||
@@ -76,3 +79,39 @@ fn generate_self_signed_cert(cert_path: &PathBuf, key_path: &PathBuf) -> anyhow:
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate a DER-encoded X.509 certificate: bail if expired, warn if expiring
|
||||
/// soon or self-signed.
|
||||
fn validate_certificate(der_bytes: &[u8]) -> anyhow::Result<()> {
|
||||
use x509_parser::prelude::*;
|
||||
|
||||
let (_, cert) = X509Certificate::from_der(der_bytes)
|
||||
.map_err(|e| anyhow::anyhow!("failed to parse X.509 certificate: {e}"))?;
|
||||
|
||||
let validity = cert.validity();
|
||||
let now = ASN1Time::now();
|
||||
|
||||
if !validity.is_valid_at(now) {
|
||||
anyhow::bail!(
|
||||
"TLS certificate expired (not_after: {})",
|
||||
validity.not_after
|
||||
);
|
||||
}
|
||||
|
||||
// Warn if expiring within 30 days.
|
||||
let thirty_days = std::time::Duration::from_secs(30 * 24 * 60 * 60);
|
||||
let cutoff = now.timestamp() + thirty_days.as_secs() as i64;
|
||||
if validity.not_after.timestamp() < cutoff {
|
||||
tracing::warn!(
|
||||
not_after = %validity.not_after,
|
||||
"TLS certificate expires within 30 days"
|
||||
);
|
||||
}
|
||||
|
||||
// Warn if self-signed (issuer == subject).
|
||||
if cert.issuer() == cert.subject() {
|
||||
tracing::warn!("TLS certificate is self-signed (issuer == subject)");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user