feat: added mTLS auth for beacons

This commit is contained in:
Andrew Rioux
2025-02-13 01:24:33 -05:00
parent f9ff9f266a
commit 75b53f7191
12 changed files with 504 additions and 432 deletions

View File

@@ -15,3 +15,5 @@ serde = "1.0"
serde_json = "1.0"
axum-server = { version = "^0.7", features = ["tokio-rustls", "tls-rustls"] }
rustls = "0.23"
rcgen = "0.13.2"
rustls-pki-types = "1.11.0"

View File

@@ -5,6 +5,8 @@ pub enum Error {
TokioJoin(tokio::task::JoinError),
Io(std::io::Error),
Rustls(rustls::Error),
Rcgen(rcgen::Error),
WebPki(rustls::client::VerifierBuilderError),
}
impl std::fmt::Display for Error {
@@ -25,6 +27,12 @@ impl std::fmt::Display for Error {
Error::Rustls(err) => {
write!(f, "rustls error: {err:?}")
}
Error::Rcgen(err) => {
write!(f, "rcgen error: {err:?}")
}
Error::WebPki(err) => {
write!(f, "webpki error: {err:?}")
}
}
}
}
@@ -36,6 +44,8 @@ impl std::error::Error for Error {
Error::TokioJoin(err) => Some(err),
Error::Io(err) => Some(err),
Error::Rustls(err) => Some(err),
Error::Rcgen(err) => Some(err),
Error::WebPki(err) => Some(err),
_ => None,
}
}
@@ -72,3 +82,15 @@ impl From<rustls::Error> for Error {
Self::Rustls(err)
}
}
impl From<rcgen::Error> for Error {
fn from(err: rcgen::Error) -> Self {
Self::Rcgen(err)
}
}
impl From<rustls::client::VerifierBuilderError> for Error {
fn from(err: rustls::client::VerifierBuilderError) -> Self {
Self::WebPki(err)
}
}

View File

@@ -4,6 +4,8 @@ use std::{
};
use axum::routing::{Router, get, post};
use rcgen::{Certificate, CertificateParams, KeyPair};
use rustls::{server::WebPkiClientVerifier, RootCertStore};
use sqlx::SqlitePool;
use tokio::task::JoinHandle;
@@ -114,18 +116,49 @@ pub async fn start_listener(
let hidden_app = Router::new().nest("/hidden_sparse", app);
let keypair = match rustls::pki_types::PrivateKeyDer::try_from(listener.privkey.clone()) {
Ok(pk) => pk,
Err(e) => {
let ca_cert = rustls::pki_types::CertificateDer::from(listener.certificate.clone());
let (keypair, cert) = {
let ca_keypair = KeyPair::from_der_and_sign_algo(
&rustls_pki_types::PrivateKeyDer::try_from(&*listener.privkey)
.map_err(|_| rcgen::Error::CouldNotParseCertificate)?,
&rcgen::PKCS_ECDSA_P256_SHA256,
)?;
let ca_params = CertificateParams::from_ca_cert_der(&(*listener.certificate).into())
.map_err(|_| rcgen::Error::CouldNotParseCertificate)?;
let ca_cert = ca_params.self_signed(&ca_keypair)?;
let server_key = KeyPair::generate()?;
let Ok(server_params) = CertificateParams::new(
vec![listener.domain_name.clone()]
) else {
return Err(crate::error::Error::Generic(format!(
"Could not parse private key: {e}"
"Could not generate new server keychain"
)));
}
};
let server_cert = server_params.signed_by(&server_key, &ca_cert, &ca_keypair)?;
let keypair = match rustls::pki_types::PrivateKeyDer::try_from(server_key.serialize_der()) {
Ok(pk) => pk,
Err(e) => {
return Err(crate::error::Error::Generic(format!(
"Could not parse private key: {e}"
)));
}
};
let cert = server_cert.into();
(keypair, cert)
};
let cert = rustls::pki_types::CertificateDer::from(listener.certificate.clone());
let mut root_store = RootCertStore::empty();
root_store.add(ca_cert)?;
let client_verifier = WebPkiClientVerifier::builder(root_store.into())
.build()?;
let mut tls_config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_client_cert_verifier(client_verifier)
.with_single_cert(vec![cert], keypair)?;
tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];