@@ -291,13 +291,11 @@ impl PolicyServer {
291
291
}
292
292
}
293
293
294
- /// Load the ServerConfig to be used by the Policy Server configuring the server
295
- /// certificate and mTLS when necessary
296
- ///
297
- /// RustlsConfig does not offer a function to load the client CA certificate together with the
298
- /// service certificates. Therefore, we need to load everything and build the ServerConfig
299
- async fn build_tls_server_config ( tls_config : & TlsConfig ) -> Result < rustls:: ServerConfig > {
300
- let cert_reader = & mut BufReader :: new ( File :: open ( tls_config. cert_file . clone ( ) ) ?) ;
294
+ async fn load_server_cert_and_key (
295
+ cert_file : String ,
296
+ key_file : String ,
297
+ ) -> Result < ( Vec < CertificateDer < ' static > > , PrivateKeyDer < ' static > ) > {
298
+ let cert_reader = & mut BufReader :: new ( File :: open ( cert_file) ?) ;
301
299
let cert: Vec < CertificateDer > = rustls_pemfile:: certs ( cert_reader)
302
300
. filter_map ( |it| {
303
301
if let Err ( ref e) = it {
@@ -311,7 +309,7 @@ async fn build_tls_server_config(tls_config: &TlsConfig) -> Result<rustls::Serve
311
309
return Err ( anyhow ! ( "Multiple certificates provided in cert file" ) ) ;
312
310
}
313
311
314
- let key_file_reader = & mut BufReader :: new ( File :: open ( tls_config . key_file . clone ( ) ) ?) ;
312
+ let key_file_reader = & mut BufReader :: new ( File :: open ( key_file) ?) ;
315
313
let mut key_vec: Vec < Vec < u8 > > = rustls_pemfile:: read_all ( key_file_reader)
316
314
. filter_map ( |i| match i. ok ( ) ? {
317
315
Item :: Sec1Key ( key) => Some ( key. secret_sec1_der ( ) . to_vec ( ) ) ,
@@ -332,11 +330,18 @@ async fn build_tls_server_config(tls_config: &TlsConfig) -> Result<rustls::Serve
332
330
let key = PrivateKeyDer :: try_from ( key_vec. pop ( ) . unwrap ( ) )
333
331
. map_err ( |e| anyhow ! ( "Cannot parse server key: {e}" ) ) ?;
334
332
335
- if let Some ( client_ca_file) = tls_config. client_ca_file . clone ( ) {
333
+ Ok ( ( cert, key) )
334
+ }
335
+
336
+ async fn load_client_cas (
337
+ client_cas : Vec < std:: path:: PathBuf > ,
338
+ ) -> Result < Arc < dyn rustls:: server:: danger:: ClientCertVerifier > > {
339
+ let mut store = RootCertStore :: empty ( ) ;
340
+ //mTLS enabled
341
+ for client_ca_file in client_cas {
336
342
// we have the client CA. Therefore, we should enable mTLS.
337
343
let client_ca_reader = & mut BufReader :: new ( File :: open ( client_ca_file) ?) ;
338
344
339
- let mut store = RootCertStore :: empty ( ) ;
340
345
let client_ca_certs: Vec < _ > = rustls_pemfile:: certs ( client_ca_reader)
341
346
. filter_map ( |it| {
342
347
if let Err ( ref e) = it {
@@ -351,15 +356,30 @@ async fn build_tls_server_config(tls_config: &TlsConfig) -> Result<rustls::Serve
351
356
client_ca_certs_ignored = cert_ignored,
352
357
"Loaded client CA certificates"
353
358
) ;
354
- let client_verifier = WebPkiClientVerifier :: builder ( Arc :: new ( store) ) . build ( ) ?;
359
+ }
360
+ WebPkiClientVerifier :: builder ( Arc :: new ( store) )
361
+ . build ( )
362
+ . map_err ( |e| anyhow ! ( "Cannot build client verifier: {e}" ) )
363
+ }
355
364
365
+ /// Load the ServerConfig to be used by the Policy Server configuring the server
366
+ /// certificate and mTLS when necessary
367
+ ///
368
+ /// RustlsConfig does not offer a function to load the client CA certificate together with the
369
+ /// service certificates. Therefore, we need to load everything and build the ServerConfig
370
+ async fn build_tls_server_config ( tls_config : & TlsConfig ) -> Result < rustls:: ServerConfig > {
371
+ let ( cert, key) =
372
+ load_server_cert_and_key ( tls_config. cert_file . clone ( ) , tls_config. key_file . clone ( ) ) . await ?;
373
+
374
+ if tls_config. client_ca_file . is_empty ( ) {
356
375
return Ok ( ServerConfig :: builder ( )
357
- . with_client_cert_verifier ( client_verifier )
376
+ . with_no_client_auth ( )
358
377
. with_single_cert ( cert, key) ?) ;
359
378
}
360
379
380
+ let client_verifier = load_client_cas ( tls_config. client_ca_file . clone ( ) ) . await ?;
361
381
Ok ( ServerConfig :: builder ( )
362
- . with_no_client_auth ( )
382
+ . with_client_cert_verifier ( client_verifier )
363
383
. with_single_cert ( cert, key) ?)
364
384
}
365
385
@@ -385,11 +405,12 @@ async fn create_tls_config_and_watch_certificate_changes(
385
405
) -> Result < RustlsConfig > {
386
406
use :: tracing:: error;
387
407
388
- let config = build_tls_server_config ( & tls_config ) . await ? ;
389
-
390
- let rust_config = RustlsConfig :: from_config ( Arc :: new ( config ) ) ;
408
+ // Build initial TLS configuration
409
+ let initial_config = build_tls_server_config ( & tls_config ) . await ? ;
410
+ let rust_config = RustlsConfig :: from_config ( Arc :: new ( initial_config ) ) ;
391
411
let reloadable_rust_config = rust_config. clone ( ) ;
392
412
413
+ // Init inotify to watch for changes in the certificate files
393
414
let inotify =
394
415
inotify:: Inotify :: init ( ) . map_err ( |e| anyhow ! ( "Cannot initialize inotify: {e}" ) ) ?;
395
416
let cert_watch = inotify
@@ -404,15 +425,18 @@ async fn create_tls_config_and_watch_certificate_changes(
404
425
. add ( tls_config. key_file . clone ( ) , inotify:: WatchMask :: CLOSE_WRITE )
405
426
. map_err ( |e| anyhow ! ( "Cannot watch key file: {e}" ) ) ?;
406
427
407
- let mut client_cert_watch = None ;
408
- if let Some ( ref client_ca_file) = tls_config. client_ca_file {
409
- client_cert_watch = Some (
428
+ let client_cert_watches = tls_config
429
+ . client_ca_file
430
+ . clone ( )
431
+ . into_iter ( )
432
+ . map ( |path| {
410
433
inotify
411
434
. watches ( )
412
- . add ( client_ca_file, inotify:: WatchMask :: CLOSE_WRITE )
413
- . map_err ( |e| anyhow ! ( "Cannot watch client certificate file: {e}" ) ) ?,
414
- ) ;
415
- }
435
+ . add ( path, inotify:: WatchMask :: CLOSE_WRITE )
436
+ . map_err ( |e| anyhow ! ( "Cannot watch client certificate file: {e}" ) )
437
+ . unwrap ( )
438
+ } )
439
+ . collect :: < Vec < _ > > ( ) ;
416
440
417
441
let buffer = [ 0 ; 1024 ] ;
418
442
let stream = inotify
@@ -442,7 +466,8 @@ async fn create_tls_config_and_watch_certificate_changes(
442
466
info ! ( "TLS key file has been modified" ) ;
443
467
key_changed = true ;
444
468
}
445
- if let Some ( ref client_cert_watch) = client_cert_watch {
469
+
470
+ for client_cert_watch in client_cert_watches. iter ( ) {
446
471
if event. wd == * client_cert_watch {
447
472
info ! ( "TLS client certificate file has been modified" ) ;
448
473
client_cert_changed = true ;
@@ -454,11 +479,12 @@ async fn create_tls_config_and_watch_certificate_changes(
454
479
if ( key_changed && cert_changed)
455
480
|| ( client_cert_changed && ( key_changed == cert_changed) )
456
481
{
457
- info ! ( "reloading TLS certificates" ) ;
482
+ info ! ( "Reloading TLS certificates" ) ;
458
483
459
484
cert_changed = false ;
460
485
key_changed = false ;
461
486
client_cert_changed = false ;
487
+
462
488
let server_config = build_tls_server_config ( & tls_config) . await ;
463
489
if let Err ( e) = server_config {
464
490
error ! ( "Failed to reload TLS certificate: {}" , e) ;
@@ -468,7 +494,6 @@ async fn create_tls_config_and_watch_certificate_changes(
468
494
}
469
495
}
470
496
} ) ;
471
-
472
497
Ok ( rust_config)
473
498
}
474
499
0 commit comments