trz_gateway_server/server/
mod.rs1use std::net::SocketAddr;
4use std::net::ToSocketAddrs;
5use std::path::PathBuf;
6use std::pin::Pin;
7use std::sync::Arc;
8use std::sync::Mutex;
9use std::time::Duration;
10
11use autoclone::autoclone;
12use axum_server::Handle;
13use axum_server::accept::DefaultAcceptor;
14use axum_server::tls_rustls::RustlsAcceptor;
15use axum_server::tls_rustls::RustlsConfig;
16use futures::FutureExt;
17use futures::future::Shared;
18use gateway_config::app_config::AppConfig;
19use http_or_https::HttpOrHttps;
20use hyper_util::rt::TokioTimer;
21use nameth::NamedEnumValues as _;
22use nameth::nameth;
23use rustls::ClientConfig;
24use tokio::sync::oneshot;
25use tokio_rustls::TlsConnector;
26use tracing::Instrument as _;
27use tracing::debug;
28use tracing::error;
29use tracing::info;
30use tracing::info_span;
31use trz_gateway_common::certificate_info::X509CertificateInfo;
32use trz_gateway_common::dynamic_config::DynamicConfig;
33use trz_gateway_common::dynamic_config::mode::RO;
34use trz_gateway_common::handle::ServerHandle;
35use trz_gateway_common::is_global::IsGlobalError;
36use trz_gateway_common::security_configuration::HasDynamicSecurityConfig;
37use trz_gateway_common::security_configuration::certificate::CertificateConfig;
38use trz_gateway_common::security_configuration::certificate::tls_server::ToTlsServer;
39use trz_gateway_common::security_configuration::certificate::tls_server::ToTlsServerError;
40use trz_gateway_common::security_configuration::custom_server_certificate_verifier::SignedExtensionCertificateVerifier;
41use trz_gateway_common::security_configuration::trusted_store::TrustedStoreConfig;
42use trz_gateway_common::security_configuration::trusted_store::cache::CachedTrustedStoreConfig;
43use trz_gateway_common::security_configuration::trusted_store::tls_client::ToTlsClient;
44use trz_gateway_common::security_configuration::trusted_store::tls_client::ToTlsClientError;
45use trz_gateway_common::tracing::EnableTracingError;
46
47use self::gateway_config::GatewayConfig;
48use self::issuer_config::IssuerConfig;
49use self::issuer_config::IssuerConfigError;
50use crate::connection::Connections;
51
52pub mod acme;
53mod app;
54mod certificate;
55pub mod gateway_config;
56mod http_or_https;
57mod issuer_config;
58pub mod root_ca_configuration;
59mod tunnel;
60
61#[cfg(test)]
62mod tests;
63
64const HTTP_TIMEOUT: Duration = if cfg!(test) {
65 Duration::from_secs(3)
66} else {
67 Duration::from_secs(60 * 5)
68};
69
70pub struct Server {
72 shutdown: Shared<Pin<Box<dyn Future<Output = ()> + Send + Sync>>>,
73 root_ca: Arc<X509CertificateInfo>,
74 tls_server: RustlsConfig,
75 tls_client: Arc<DynamicConfig<Result<TlsConnector, Arc<dyn IsGlobalError>>, RO>>,
76 connections: Arc<Connections>,
77 issuer_config: Arc<DynamicConfig<Result<Arc<IssuerConfig>, Arc<dyn IsGlobalError>>, RO>>,
78 app_config: Box<dyn AppConfig>,
79 set_current_endpoint: Option<PathBuf>,
80}
81
82impl Server {
83 pub async fn run<C: GatewayConfig>(
90 config: C,
91 ) -> Result<
92 (
93 Arc<Self>,
94 ServerHandle<()>,
95 oneshot::Receiver<RunGatewayError>,
96 ),
97 GatewayError<C>,
98 > {
99 if config.enable_tracing() {
100 trz_gateway_common::tracing::enable_tracing()?;
101 }
102
103 let _span = info_span!("Server").entered();
104
105 let (shutdown_rx, terminated_tx, handle) = ServerHandle::new("Server");
106 let shutdown_rx: Pin<Box<dyn Future<Output = ()> + Send + Sync>> = Box::pin(shutdown_rx);
107
108 let root_ca_config = config.root_ca();
109 let root_ca = root_ca_config
110 .certificate()
111 .map_err(|error| GatewayError::RootCa(Box::new(error)))?;
112 info!("Root CA: {:?}", root_ca.certificate.subject_name());
113 debug!("Root CA details: {}", root_ca.display());
114
115 let tls_server = config.tls().to_tls_server()?;
116 debug!("Got TLS server config");
117
118 let dynamic_client_config_view =
119 config
120 .client_certificate_issuer()
121 .as_dyn()
122 .view(move |client_certificate_issuer| {
123 Arc::new(
124 make_client_config_view(&root_ca_config, client_certificate_issuer)
125 .map_err(Arc::<GatewayError<C>>::new),
126 )
127 });
128
129 let server = Arc::new(Self {
130 shutdown: shutdown_rx.shared(),
131 root_ca,
132 tls_server: RustlsConfig::from_config(tls_server),
133 tls_client: dynamic_client_config_view.view(|tls_client| {
134 (*(tls_client.as_ref()))
135 .as_ref()
136 .map(|view| TlsConnector::from(view.tls_client.clone()))
137 .map_err(|x| x.clone() as Arc<dyn IsGlobalError>)
138 }),
139 connections: Arc::new(Connections::default()),
140 issuer_config: dynamic_client_config_view.view(|tls_client| {
141 (*(tls_client.as_ref()))
142 .as_ref()
143 .map(|view| view.issuer_config.clone())
144 .map_err(|x| x.clone() as Arc<dyn IsGlobalError>)
145 }),
146 app_config: Box::new(config.app_config()),
147 set_current_endpoint: config.set_current_endpoint(),
148 });
149
150 let (host, ports) = (config.host(), config.ports());
151 let socket_addrs = (host.as_str(), *ports.first().unwrap())
152 .to_socket_addrs()
153 .map_err(|error| GatewayError::ToSocketAddrs { host, error })?
154 .flat_map(|socket_addr| {
155 ports
156 .iter()
157 .map(move |port| SocketAddr::new(socket_addr.ip(), *port))
158 });
159 drop(config);
160
161 let mut terminated = vec![];
162 let mut handles = vec![];
163
164 let (server_crash_tx, server_crash_rx) = oneshot::channel();
165 let server_crash_tx = Arc::new(Mutex::new(Some(server_crash_tx)));
166 for socket_addr in socket_addrs {
167 let _span = info_span!("Listen", %socket_addr).entered();
168 info!("Setup server");
169 let (handle, serving) = server.clone().run_endpoint(socket_addr);
170 handles.push(handle);
171 let (terminated_tx, terminated_rx) = oneshot::channel();
172 terminated.push(terminated_rx);
173 let server_crash_tx = server_crash_tx.clone();
174 tokio::spawn(
175 async move {
176 match serving.await {
177 Ok(()) => (),
178 Err(error) => {
179 error!("Failed {error}");
180 if let Some(server_crash_tx) =
181 server_crash_tx.lock().expect("server_crash_tx").take()
182 {
183 let _ = server_crash_tx.send(error);
184 }
185 }
186 }
187 let _: Result<(), ()> = terminated_tx.send(());
188 }
189 .in_current_span(),
190 );
191 }
192
193 if let Some(set_current_endpoint) = server.set_current_endpoint.clone() {
194 use futures::future::join_all;
195 let current_endpoints = join_all(handles.into_iter().map(|handle| async move {
196 handle
197 .listening()
198 .await
199 .filter(SocketAddr::is_ipv4)
200 .map(|local_addr| format!("{}:{}", local_addr.ip(), local_addr.port()))
201 }))
202 .await
203 .into_iter()
204 .flatten()
205 .collect::<Vec<_>>();
206 info!("Reporting current endpoints as: {current_endpoints:?}");
207 std::fs::write(set_current_endpoint, current_endpoints.join(";"))
208 .expect("write endpoint to file");
209 }
210
211 {
212 use futures::future::join_all;
213 let all_terminated = join_all(terminated);
214 tokio::spawn(
215 async move {
216 let _: Vec<Result<(), oneshot::error::RecvError>> = all_terminated.await;
217 let _: Result<(), ()> = terminated_tx.send(());
218 }
219 .in_current_span(),
220 );
221 }
222 Ok((server, handle, server_crash_rx))
223 }
224
225 #[autoclone]
226 fn run_endpoint(
227 self: Arc<Self>,
228 socket_addr: SocketAddr,
229 ) -> (
230 Handle<SocketAddr>,
231 impl Future<Output = Result<(), RunGatewayError>>,
232 ) {
233 let app = self.make_app();
234
235 let handle = Handle::new();
236 let mut axum_server = axum_server::bind(socket_addr)
237 .acceptor(HttpOrHttps {
238 tls: RustlsAcceptor::new(self.tls_server.clone()),
239 plaintext: DefaultAcceptor,
240 })
241 .handle(handle.clone());
242 axum_server
243 .http_builder()
244 .http1()
245 .timer(TokioTimer::new())
246 .header_read_timeout(HTTP_TIMEOUT)
247 .http2()
248 .timer(TokioTimer::new())
249 .keep_alive_timeout(HTTP_TIMEOUT);
250
251 let shutdown = self.shutdown.clone();
252 tokio::spawn(
253 async move {
254 autoclone!(handle);
255 let () = shutdown.await;
256 handle.shutdown();
257 }
258 .in_current_span(),
259 );
260
261 let serving = async move {
262 info!("Serving...");
263 let () = axum_server
264 .serve(app.into_make_service_with_connect_info::<SocketAddr>())
265 .await
266 .map_err(RunGatewayError::Serve)?;
267 info!("Serving: done");
268 Ok(())
269 };
270 (handle, serving)
271 }
272
273 pub fn connections(&self) -> &Connections {
275 &self.connections
276 }
277}
278
279fn make_client_config_view<C: GatewayConfig>(
280 root_ca: &C::RootCaConfig,
281 client_certificate_issuer: &<C::ClientCertificateIssuerConfig as HasDynamicSecurityConfig>::HasSecurityConfig,
282) -> Result<ClientConfigView, GatewayError<C>> {
283 let issuer_config = IssuerConfig::new(client_certificate_issuer)?;
284 info!("Signer certificate: {:?}", issuer_config.signer_name);
285 debug!(
286 "Signer certificate details: {}",
287 issuer_config.signer.display()
288 );
289
290 let tls_client = root_ca.to_tls_client(SignedExtensionCertificateVerifier {
294 store: CachedTrustedStoreConfig::new(client_certificate_issuer.clone())
295 .map_err(GatewayError::CachedTrustedStoreConfig)?,
296 signer_name: issuer_config.signer_name.clone(),
297 })?;
298 debug!("Got TLS client config");
299 Ok(ClientConfigView {
300 issuer_config: Arc::new(issuer_config),
301 tls_client: Arc::new(tls_client),
302 })
303}
304
305struct ClientConfigView {
306 issuer_config: Arc<IssuerConfig>,
307 tls_client: Arc<ClientConfig>,
308}
309
310#[nameth]
311#[derive(thiserror::Error, Debug)]
312pub enum GatewayError<C: GatewayConfig> {
313 #[error("[{n}] {0}", n = self.name())]
314 EnableTracing(#[from] EnableTracingError),
315
316 #[error("[{n}] Failed to get Root CA: {0}", n = self.name())]
317 RootCa(Box<dyn IsGlobalError>),
318
319 #[error("[{n}] Failed to get the client certificate issuer configuration: {0}", n = self.name())]
320 IssuerConfig(#[from] IssuerConfigError<<C::ClientCertificateIssuerConfig as HasDynamicSecurityConfig>::HasSecurityConfig>),
321
322 #[error("[{n}] Failed to get socket address for host={host}: {error}", n = self.name())]
323 ToSocketAddrs {
324 host: String,
325 error: std::io::Error,
326 },
327
328 #[error("[{n}] {0}", n = self.name())]
329 ToTlsServerConfig(#[from] ToTlsServerError<<C::TlsConfig as CertificateConfig>::Error>),
330
331 #[error("[{n}] {0}", n = self.name())]
332 ToTlsClientConfig(#[from] ToTlsClientError<<C::RootCaConfig as TrustedStoreConfig>::Error>),
333
334 #[error("[{n}] {0}", n = self.name())]
335 CachedTrustedStoreConfig(<<C::ClientCertificateIssuerConfig as HasDynamicSecurityConfig>::HasSecurityConfig as TrustedStoreConfig>::Error),
336
337 #[error("[{n}] {0}", n = self.name())]
338 RunGatewayError(#[from] RunGatewayError),
339}
340
341#[nameth]
342#[derive(thiserror::Error, Debug)]
343pub enum RunGatewayError {
344 #[error("[{n}] {0}", n = self.name())]
345 Serve(std::io::Error),
346}