authly_common/
mtls_server.rs1use http::Request;
4use hyper::body::Incoming;
5use tracing::warn;
6use x509_parser::prelude::{FromDer, X509Certificate};
7
8use crate::{certificate::oid::ENTITY_UNIQUE_IDENTIFIER, id::ServiceId};
9
10#[derive(Clone, Copy, Debug)]
12pub struct PeerServiceEntity(pub ServiceId);
13
14#[derive(Clone)]
16pub struct MTLSMiddleware;
17
18#[derive(Default)]
20pub struct MTLSConnectionData {
21 peer_service_entity: Option<ServiceId>,
22}
23
24impl MTLSConnectionData {
25 pub fn peer_service_entity(&self) -> Option<ServiceId> {
27 self.peer_service_entity
28 }
29}
30
31impl tower_server::tls::TlsConnectionMiddleware for MTLSMiddleware {
32 type Data = Option<MTLSConnectionData>;
33
34 fn data(&self, connection: &rustls::ServerConnection) -> Self::Data {
35 let peer_der = connection.peer_certificates()?.first()?;
36 let (_, peer_cert) = X509Certificate::from_der(peer_der).ok()?;
37
38 let mut data = MTLSConnectionData::default();
39
40 for rdn in peer_cert.subject.iter() {
41 for attr in rdn.iter() {
42 if let Some(attr_type) = attr.attr_type().iter() {
43 if attr_type.eq(ENTITY_UNIQUE_IDENTIFIER.iter().copied()) {
44 if let Ok(value) = attr.attr_value().as_str() {
45 if let Ok(entity_id) = value.parse() {
46 data.peer_service_entity = Some(entity_id);
47 } else {
48 warn!("failed to parse entity ID: `{value}`");
49 }
50 }
51 }
52 } else {
53 warn!("unparsable attribute");
54 }
55 }
56 }
57
58 Some(data)
59 }
60
61 fn call(&self, req: &mut Request<Incoming>, data: &Self::Data) {
62 let Some(data) = data else {
63 return;
64 };
65 if let Some(id) = data.peer_service_entity {
66 req.extensions_mut().insert(PeerServiceEntity(id));
67 }
68 }
69}