use super::cedar_authorizer::CedarAuthorizer; use super::check_service::CheckService; use envoy_types::ext_authz::v3::pb::AuthorizationServer; use std::sync::Arc; pub struct Server { router: tonic::transport::server::Router, } impl Server { pub fn new() -> Result> { let (health_reporter, health_service) = tonic_health::server::health_reporter(); std::mem::drop( health_reporter.set_service_status("", tonic_health::ServingStatus::Serving), ); let authorization_service = AuthorizationServer::new(CheckService::new(Arc::new(CedarAuthorizer::default()))); let reflection_service = tonic_reflection::server::Builder::configure() .register_encoded_file_descriptor_set(tonic_health::pb::FILE_DESCRIPTOR_SET) .register_encoded_file_descriptor_set(include_bytes!( "../../vendor/envoy-types/src/generated/types.bin" )) .build_v1()?; Ok(Self::new_with(|mut builder| { builder .add_service(authorization_service) .add_service(health_service) .add_service(reflection_service) })) } pub fn new_with(f: F) -> Server where F: FnOnce(tonic::transport::Server) -> tonic::transport::server::Router, { let builder = tonic::transport::Server::builder() .trace_fn(|req| { tracing::info!( method = %req.method(), path = %req.uri().path(), content_type = ?req.headers().get("content-type").and_then(|v| v.to_str().ok()), user_agent = ?req.headers().get("user-agent").and_then(|v| v.to_str().ok()), x_request_id = ?req.headers().get("x-request-id").and_then(|v| v.to_str().ok()), "gRPC request" ); tracing::info_span!( "request", method = %req.method(), path = %req.uri().path(), ) }) .timeout(std::time::Duration::from_secs(30)); let router = f(builder); Server { router } } pub async fn serve(self, addr: std::net::SocketAddr) -> Result<(), tonic::transport::Error> { self.router.serve(addr).await } } impl Default for Server { fn default() -> Self { Self::new().unwrap() } }