11use std:: {
22 collections:: HashMap ,
3- fs:: read_to_string,
43 net:: { IpAddr , Ipv4Addr , SocketAddr } ,
54 path:: Path ,
6- sync:: { atomic:: Ordering , Arc , LazyLock , RwLock } ,
5+ sync:: { atomic:: Ordering , Arc , RwLock } ,
76 time:: Duration ,
87} ;
98
@@ -21,11 +20,7 @@ use axum_extra::extract::cookie::Key;
2120use clap:: crate_version;
2221use defguard_version:: { server:: DefguardVersionLayer , Version } ;
2322use serde:: Serialize ;
24- use tokio:: {
25- net:: TcpListener ,
26- sync:: { oneshot, Mutex } ,
27- task:: JoinSet ,
28- } ;
23+ use tokio:: { net:: TcpListener , sync:: oneshot, task:: JoinSet } ;
2924use tower_governor:: {
3025 governor:: GovernorConfigBuilder , key_extractor:: SmartIpKeyExtractor , GovernorLayer ,
3126} ;
@@ -35,13 +30,13 @@ use url::Url;
3530
3631use crate :: {
3732 assets:: { index, web_asset} ,
38- config:: Config ,
33+ config:: EnvConfig ,
3934 enterprise:: handlers:: openid_login:: { self , FlowType } ,
4035 error:: ApiError ,
4136 grpc:: { Configuration , ProxyServer } ,
4237 handlers:: { desktop_client_mfa, enrollment, password_reset, polling} ,
4338 setup:: ProxySetupServer ,
44- CommsChannel , VERSION ,
39+ LogsReceiver , VERSION ,
4540} ;
4641
4742pub ( crate ) static ENROLLMENT_COOKIE_NAME : & str = "defguard_proxy" ;
@@ -51,13 +46,8 @@ const DEFGUARD_CORE_VERSION_HEADER: &str = "defguard-core-version";
5146const RATE_LIMITER_CLEANUP_PERIOD : Duration = Duration :: from_secs ( 60 ) ;
5247const X_FORWARDED_FOR : & str = "x-forwarded-for" ;
5348const X_POWERED_BY : & str = "x-powered-by" ;
54- const GRPC_CERT_NAME : & str = "proxy_grpc_cert.pem" ;
55- const GRPC_KEY_NAME : & str = "proxy_grpc_key.pem" ;
56-
57- pub static GRPC_SERVER_RESTART_CHANNEL : LazyLock < CommsChannel < ( ) > > = LazyLock :: new ( || {
58- let ( tx, rx) = tokio:: sync:: mpsc:: channel ( 100 ) ;
59- ( Arc :: new ( Mutex :: new ( tx) ) , Arc :: new ( Mutex :: new ( rx) ) )
60- } ) ;
49+ pub const GRPC_CERT_NAME : & str = "proxy_grpc_cert.pem" ;
50+ pub const GRPC_KEY_NAME : & str = "proxy_grpc_key.pem" ;
6151
6252#[ derive( Clone ) ]
6353pub ( crate ) struct AppState {
@@ -177,6 +167,45 @@ async fn powered_by_header<B>(mut response: Response<B>) -> Response<B> {
177167 response
178168}
179169
170+ pub async fn run_setup (
171+ env_config : & EnvConfig ,
172+ logs_rx : LogsReceiver ,
173+ ) -> anyhow:: Result < Configuration > {
174+ let setup_server = ProxySetupServer :: new ( logs_rx) ;
175+ let cert_dir = Path :: new ( & env_config. cert_dir ) ;
176+ if !cert_dir. exists ( ) {
177+ tokio:: fs:: create_dir_all ( cert_dir) . await ?;
178+ }
179+
180+ // Only attempt setup if not already configured
181+ info ! (
182+ "No gRPC TLS certificates found at {}, new certificates will be obtained during setup" ,
183+ cert_dir. display( )
184+ ) ;
185+ let configuration = setup_server
186+ . await_initial_setup ( SocketAddr :: new (
187+ env_config
188+ . grpc_bind_address
189+ . unwrap_or ( IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) ) ,
190+ env_config. grpc_port ,
191+ ) )
192+ . await ?;
193+ info ! ( "Generated new gRPC TLS certificates and signed by Defguard Core" ) ;
194+
195+ let Configuration {
196+ grpc_cert_pem,
197+ grpc_key_pem,
198+ ..
199+ } = & configuration;
200+
201+ let cert_path = cert_dir. join ( GRPC_CERT_NAME ) ;
202+ let key_path = cert_dir. join ( GRPC_KEY_NAME ) ;
203+ tokio:: fs:: write ( & cert_path, grpc_cert_pem) . await ?;
204+ tokio:: fs:: write ( & key_path, grpc_key_pem) . await ?;
205+
206+ Ok ( configuration)
207+ }
208+
180209/// Middleware that gates all HTTP endpoints except health checks until the proxy
181210/// is fully configured.
182211///
@@ -206,9 +235,9 @@ async fn ensure_configured(
206235 next. run ( request) . await
207236}
208237
209- pub async fn run_server ( config : Config ) -> anyhow:: Result < ( ) > {
238+ pub async fn run_server ( env_config : EnvConfig , config : Configuration ) -> anyhow:: Result < ( ) > {
210239 info ! ( "Starting Defguard Proxy server" ) ;
211- debug ! ( "Using config: {config :?}" ) ;
240+ debug ! ( "Using config: {env_config :?}" ) ;
212241
213242 let mut tasks = JoinSet :: new ( ) ;
214243 let cookie_key = Default :: default ( ) ;
@@ -217,68 +246,20 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> {
217246 let grpc_server = ProxyServer :: new ( Arc :: clone ( & cookie_key) ) ;
218247
219248 let server_clone = grpc_server. clone ( ) ;
220-
221- let setup_server = ProxySetupServer :: new ( ) ;
249+ grpc_server. configure ( config) ;
222250
223251 // Start gRPC server.
224252 // TODO: Wait with spawning the HTTP server until gRPC server is ready.
225253 debug ! ( "Spawning gRPC server" ) ;
226254 tasks. spawn ( async move {
227- let cert_dir = Path :: new ( & config. cert_dir ) ;
228- if !cert_dir. exists ( ) {
229- debug ! ( "Creating certs directory" ) ;
230- tokio:: fs:: create_dir_all ( cert_dir) . await ?;
231- }
232-
233255 loop {
256+ info ! ( "Starting gRPC server..." ) ;
234257 let server_to_run = server_clone. clone ( ) ;
235-
236- if let ( Some ( cert) , Some ( key) ) = (
237- read_to_string ( cert_dir. join ( GRPC_CERT_NAME ) ) . ok ( ) ,
238- read_to_string ( cert_dir. join ( GRPC_KEY_NAME ) ) . ok ( ) ,
239- ) {
240- info ! (
241- "Using existing gRPC TLS certificates from {}" ,
242- cert_dir. display( )
243- ) ;
244- server_clone. set_tls_config ( cert, key) ?;
245- } else if !server_clone. setup_completed ( ) {
246- // Only attempt setup if not already configured
247- info ! (
248- "No gRPC TLS certificates found at {}, new certificates will be generated" ,
249- cert_dir. display( )
250- ) ;
251- let configuration = setup_server
252- . await_setup ( SocketAddr :: new (
253- config
254- . grpc_bind_address
255- . unwrap_or ( IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) ) ,
256- config. grpc_port ,
257- ) )
258- . await ?;
259- info ! ( "Generated new gRPC TLS certificates and signed by Defguard Core" ) ;
260-
261- let Configuration {
262- grpc_cert_pem,
263- grpc_key_pem,
264- ..
265- } = & configuration;
266-
267- let cert_path = cert_dir. join ( GRPC_CERT_NAME ) ;
268- let key_path = cert_dir. join ( GRPC_KEY_NAME ) ;
269- tokio:: fs:: write ( & cert_path, grpc_cert_pem) . await ?;
270- tokio:: fs:: write ( & key_path, grpc_key_pem) . await ?;
271-
272- server_to_run. configure ( configuration) ;
273- } else {
274- info ! ( "Proxy already configured, skipping setup phase" ) ;
275- }
276-
277258 let addr = SocketAddr :: new (
278- config
259+ env_config
279260 . grpc_bind_address
280261 . unwrap_or ( IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) ) ,
281- config . grpc_port ,
262+ env_config . grpc_port ,
282263 ) ;
283264
284265 if let Err ( e) = server_to_run. run ( addr) . await {
@@ -293,18 +274,18 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> {
293274 cookie_key,
294275 grpc_server,
295276 remote_mfa_sessions : Arc :: new ( tokio:: sync:: Mutex :: new ( HashMap :: new ( ) ) ) ,
296- url : config . url . clone ( ) ,
277+ url : env_config . url . clone ( ) ,
297278 } ;
298279
299280 // Setup tower_governor rate-limiter
300281 debug ! (
301282 "Configuring rate limiter, per_second: {}, burst: {}" ,
302- config . rate_limit_per_second, config . rate_limit_burst
283+ env_config . rate_limit_per_second, env_config . rate_limit_burst
303284 ) ;
304285 let governor_conf = GovernorConfigBuilder :: default ( )
305286 . key_extractor ( SmartIpKeyExtractor )
306- . per_second ( config . rate_limit_per_second )
307- . burst_size ( config . rate_limit_burst )
287+ . per_second ( env_config . rate_limit_per_second )
288+ . burst_size ( env_config . rate_limit_burst )
308289 . finish ( ) ;
309290
310291 let governor_conf = if let Some ( conf) = governor_conf {
@@ -323,7 +304,7 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> {
323304 } ) ;
324305 info ! (
325306 "Configured rate limiter, per_second: {}, burst: {}" ,
326- config . rate_limit_per_second, config . rate_limit_burst
307+ env_config . rate_limit_per_second, env_config . rate_limit_burst
327308 ) ;
328309 Some ( conf)
329310 } else {
@@ -385,10 +366,10 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> {
385366 debug ! ( "Spawning API web server" ) ;
386367 tasks. spawn ( async move {
387368 let addr = SocketAddr :: new (
388- config
369+ env_config
389370 . http_bind_address
390371 . unwrap_or ( IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) ) ,
391- config . http_port ,
372+ env_config . http_port ,
392373 ) ;
393374 let listener = TcpListener :: bind ( & addr) . await ?;
394375 info ! ( "API web server is listening on {addr}" ) ;
0 commit comments