clementine_core/rpc/
interceptors.rs1use tonic::{service::Interceptor, transport::CertificateDer, Request, Status};
2
3#[derive(Debug, Clone)]
4pub enum Interceptors {
5 OnlyAggregatorAndSelf {
6 aggregator_cert: CertificateDer<'static>,
7 our_cert: CertificateDer<'static>,
8 },
9 Noop,
10}
11
12fn is_internal(req: &Request<()>) -> bool {
13 let Some(path) = req.metadata().get("grpc-method") else {
15 tracing::error!("Missing grpc-method header in request");
17 return false;
18 };
19 path.as_bytes().starts_with(b"Internal")
20}
21
22impl Interceptor for Interceptors {
23 #[allow(clippy::result_large_err)]
24 fn call(&mut self, req: Request<()>) -> Result<Request<()>, Status> {
25 match self {
26 Interceptors::OnlyAggregatorAndSelf {
27 our_cert,
28 aggregator_cert,
29 } => only_aggregator_and_self(req, our_cert, aggregator_cert),
30 Interceptors::Noop => Ok(req),
31 }
32 }
33}
34
35#[allow(clippy::result_large_err)]
36fn only_aggregator_and_self(
37 req: Request<()>,
38 our_cert: &CertificateDer<'static>,
39 aggregator_cert: &CertificateDer<'static>,
40) -> Result<Request<()>, Status> {
41 let Some(peer_certs) = req.peer_certs() else {
42 if cfg!(test) {
43 return Ok(req);
45 } else {
46 return Err(Status::unauthenticated(
48 "Failed to verify peer certificate, is TLS enabled?",
49 ));
50 }
51 };
52
53 if is_internal(&req) {
54 if peer_certs.contains(our_cert) {
55 Ok(req)
56 } else {
57 Err(Status::unauthenticated(
58 "Unauthorized call to internal method (not self)",
59 ))
60 }
61 } else if peer_certs.contains(aggregator_cert) || peer_certs.contains(our_cert) {
62 Ok(req)
63 } else {
64 Err(Status::unauthenticated(
65 "Unauthorized call to method (not aggregator or self)",
66 ))
67 }
68}