@@ -43,6 +43,16 @@ const CLIENT_TLS_DIR: &str = "/etc/openshell-tls/client";
4343const SIDECAR_CLIENT_TLS_SUBDIR : & str = "client" ;
4444#[ cfg( target_os = "linux" ) ]
4545const CLIENT_TLS_FILES : [ & str ; 3 ] = [ "ca.crt" , "tls.crt" , "tls.key" ] ;
46+ #[ cfg( target_os = "linux" ) ]
47+ const SIDECAR_STATE_DIR_MODE : u32 = 0o2775 ;
48+ #[ cfg( target_os = "linux" ) ]
49+ const SIDECAR_TLS_DIR_MODE : u32 = 0o755 ;
50+ #[ cfg( target_os = "linux" ) ]
51+ const SIDECAR_TLS_STAGING_DIR_MODE : u32 = 0o700 ;
52+ #[ cfg( target_os = "linux" ) ]
53+ const SIDECAR_CLIENT_TLS_DIR_MODE : u32 = 0o750 ;
54+ #[ cfg( target_os = "linux" ) ]
55+ const SIDECAR_CLIENT_TLS_FILE_MODE : u32 = 0o400 ;
4656
4757/// Which supervisor leaves are enabled in this process.
4858///
@@ -256,6 +266,35 @@ fn prepare_sidecar_directory(path: &Path, uid: u32, gid: u32, mode: u32) -> Resu
256266 Ok ( ( ) )
257267}
258268
269+ #[ cfg( target_os = "linux" ) ]
270+ fn prepare_sidecar_directory_for_current_user ( path : & Path , mode : u32 ) -> Result < ( ) > {
271+ use miette:: Context as _;
272+ use nix:: unistd:: { Gid , Uid , chown} ;
273+ use std:: os:: unix:: fs:: PermissionsExt ;
274+
275+ let uid = Uid :: current ( ) ;
276+ let gid = Gid :: current ( ) ;
277+ std:: fs:: create_dir_all ( path)
278+ . into_diagnostic ( )
279+ . wrap_err_with ( || format ! ( "failed to create sidecar directory {}" , path. display( ) ) ) ?;
280+ chown ( path, Some ( uid) , Some ( gid) )
281+ . into_diagnostic ( )
282+ . wrap_err_with ( || {
283+ format ! (
284+ "failed to chown sidecar directory {} to {}:{}" ,
285+ path. display( ) ,
286+ uid. as_raw( ) ,
287+ gid. as_raw( )
288+ )
289+ } ) ?;
290+ let mut perms = std:: fs:: metadata ( path) . into_diagnostic ( ) ?. permissions ( ) ;
291+ perms. set_mode ( mode) ;
292+ std:: fs:: set_permissions ( path, perms)
293+ . into_diagnostic ( )
294+ . wrap_err_with ( || format ! ( "failed to chmod sidecar directory {}" , path. display( ) ) ) ?;
295+ Ok ( ( ) )
296+ }
297+
259298#[ cfg( target_os = "linux" ) ]
260299fn copy_sidecar_client_tls_if_present (
261300 source_dir : & Path ,
@@ -272,7 +311,7 @@ fn copy_sidecar_client_tls_if_present(
272311 }
273312
274313 let dest_dir = sidecar_tls_dir. join ( SIDECAR_CLIENT_TLS_SUBDIR ) ;
275- prepare_sidecar_directory ( & dest_dir, uid , gid , 0o750 ) ?;
314+ prepare_sidecar_directory_for_current_user ( & dest_dir, SIDECAR_TLS_STAGING_DIR_MODE ) ?;
276315 for file_name in CLIENT_TLS_FILES {
277316 let source = source_dir. join ( file_name) ;
278317 if !source. exists ( ) {
@@ -282,6 +321,13 @@ fn copy_sidecar_client_tls_if_present(
282321 ) ) ;
283322 }
284323 let dest = dest_dir. join ( file_name) ;
324+ if dest. exists ( ) {
325+ std:: fs:: remove_file ( & dest)
326+ . into_diagnostic ( )
327+ . wrap_err_with ( || {
328+ format ! ( "failed to remove stale client TLS file {}" , dest. display( ) )
329+ } ) ?;
330+ }
285331 std:: fs:: copy ( & source, & dest)
286332 . into_diagnostic ( )
287333 . wrap_err_with ( || {
@@ -292,7 +338,7 @@ fn copy_sidecar_client_tls_if_present(
292338 )
293339 } ) ?;
294340 let mut perms = std:: fs:: metadata ( & dest) . into_diagnostic ( ) ?. permissions ( ) ;
295- perms. set_mode ( 0o400 ) ;
341+ perms. set_mode ( SIDECAR_CLIENT_TLS_FILE_MODE ) ;
296342 std:: fs:: set_permissions ( & dest, perms)
297343 . into_diagnostic ( )
298344 . wrap_err_with ( || {
@@ -308,6 +354,8 @@ fn copy_sidecar_client_tls_if_present(
308354 } ) ?;
309355 }
310356
357+ prepare_sidecar_directory ( & dest_dir, uid, gid, SIDECAR_CLIENT_TLS_DIR_MODE ) ?;
358+
311359 Ok ( ( ) )
312360}
313361
@@ -337,19 +385,23 @@ fn run_network_init(
337385 sidecar_state_dir,
338386 proxy_user_id,
339387 proxy_primary_group_id,
340- 0o2775 ,
388+ SIDECAR_STATE_DIR_MODE ,
341389 ) ?;
342- prepare_sidecar_directory (
390+ // The init container runs as uid 0 with CAP_DAC_OVERRIDE dropped. Keep the
391+ // TLS work directory owned by the init user until the client cert copy is
392+ // complete, then hand it to the long-running proxy UID.
393+ prepare_sidecar_directory_for_current_user ( sidecar_tls_dir, SIDECAR_TLS_DIR_MODE ) ?;
394+ copy_sidecar_client_tls_if_present (
395+ Path :: new ( CLIENT_TLS_DIR ) ,
343396 sidecar_tls_dir,
344397 proxy_user_id,
345398 proxy_primary_group_id,
346- 0o755 ,
347399 ) ?;
348- copy_sidecar_client_tls_if_present (
349- Path :: new ( CLIENT_TLS_DIR ) ,
400+ prepare_sidecar_directory (
350401 sidecar_tls_dir,
351402 proxy_user_id,
352403 proxy_primary_group_id,
404+ SIDECAR_TLS_DIR_MODE ,
353405 ) ?;
354406 openshell_supervisor_process:: netns:: install_sidecar_bypass_rules ( proxy_user_id)
355407}
@@ -623,4 +675,13 @@ mod tests {
623675 let err = "" . parse :: < Mode > ( ) . unwrap_err ( ) ;
624676 assert ! ( err. contains( "at least one" ) ) ;
625677 }
678+
679+ #[ cfg( target_os = "linux" ) ]
680+ #[ test]
681+ fn sidecar_tls_modes_preserve_proxy_owned_parent_and_private_client_dir ( ) {
682+ assert_eq ! ( SIDECAR_TLS_DIR_MODE , 0o755 ) ;
683+ assert_eq ! ( SIDECAR_TLS_STAGING_DIR_MODE , 0o700 ) ;
684+ assert_eq ! ( SIDECAR_CLIENT_TLS_DIR_MODE , 0o750 ) ;
685+ assert_eq ! ( SIDECAR_CLIENT_TLS_FILE_MODE , 0o400 ) ;
686+ }
626687}
0 commit comments