@@ -107,6 +107,8 @@ const BOUNDARY_CERTIFICATE_MOUNT_PATH: &str = "/.openshell/channel/sandbox/serve
107107const BOUNDARY_PRIVATE_KEY_MOUNT_PATH : & str = "/.openshell/channel/sandbox/server.key" ;
108108const SUPERVISOR_STATE_MOUNT_PATH : & str = "/.openshell/supervisor" ;
109109const SUPERVISOR_PROXY_AUTH_MOUNT_PATH : & str = "/.openshell/supervisor/upstream-proxy-auth" ;
110+ const SUPERVISOR_PROXY_CA_BUNDLE_MOUNT_PATH : & str =
111+ "/.openshell/supervisor/upstream-proxy-ca-bundle.pem" ;
110112const PROVIDER_SPIFFE_WORKLOAD_API_SOCKET_MOUNT_DIR : & str =
111113 openshell_core:: driver_utils:: PROVIDER_SPIFFE_WORKLOAD_API_SOCKET_MOUNT_DIR ;
112114const DRIVER_ADMITTED_BACKEND : & str = openshell_sandbox_backend:: BACKEND_NAME ;
@@ -218,6 +220,10 @@ pub struct DockerComputeConfig {
218220 #[ serde( flatten) ]
219221 pub upstream_proxy : UpstreamProxyConfig ,
220222
223+ /// Gateway-host PEM CA bundle trusted for the corporate proxy and for
224+ /// server certificates re-signed by a TLS-intercepting proxy.
225+ pub proxy_ca_bundle : Option < PathBuf > ,
226+
221227 /// Host UNIX socket projected into the supervisor for provider identity.
222228 pub provider_spiffe_workload_api_socket : Option < PathBuf > ,
223229
@@ -242,6 +248,7 @@ impl DockerComputeConfig {
242248 validate_image_pull_policy ( self . image_pull_policy ) ?;
243249 self . upstream_proxy . validate ( ) . map_err ( Error :: config) ?;
244250 validate_docker_proxy_auth_file ( & self . upstream_proxy ) ?;
251+ validate_docker_proxy_ca_bundle ( self ) ?;
245252 if let Some ( socket) = self . provider_spiffe_workload_api_socket . as_deref ( ) {
246253 openshell_core:: driver_utils:: validate_provider_spiffe_unix_socket ( socket)
247254 . map_err ( Error :: config) ?;
@@ -276,6 +283,7 @@ impl Default for DockerComputeConfig {
276283 sandbox_pids_limit : openshell_core:: config:: default_sandbox_pids_limit ( ) ,
277284 enable_bind_mounts : false ,
278285 upstream_proxy : UpstreamProxyConfig :: default ( ) ,
286+ proxy_ca_bundle : None ,
279287 provider_spiffe_workload_api_socket : None ,
280288 app_armor_profile : None ,
281289 }
@@ -307,6 +315,7 @@ struct DockerDriverRuntimeConfig {
307315 sandbox_pids_limit : Option < std:: num:: NonZeroI64 > ,
308316 enable_bind_mounts : bool ,
309317 upstream_proxy : UpstreamProxyConfig ,
318+ proxy_ca_bundle : Option < PathBuf > ,
310319 provider_spiffe_workload_api_socket : Option < PathBuf > ,
311320 app_armor_profile : Option < AppArmorProfile > ,
312321}
@@ -837,10 +846,7 @@ impl DockerComputeDriver {
837846 gateway_log_level : & str ,
838847 docker_config : & DockerComputeConfig ,
839848 ) -> CoreResult < Self > {
840- docker_config
841- . resource_admission
842- . validate ( )
843- . map_err ( Error :: config) ?;
849+ docker_config. validate_configuration ( gateway_bind_address) ?;
844850 let socket_path = docker_config
845851 . socket_path
846852 . clone ( )
@@ -873,15 +879,8 @@ impl DockerComputeDriver {
873879 cdi_supported,
874880 wsl_all_gpu_fallback_enabled,
875881 } ;
876- validate_sandbox_pids_limit ( docker_config. sandbox_pids_limit ) ?;
877- validate_image_pull_policy ( docker_config. image_pull_policy ) ?;
878882 validate_docker_app_armor_profile ( docker_config. app_armor_profile . as_ref ( ) , & info) ?;
879883 let gateway_port = gateway_bind_address. port ( ) ;
880- if gateway_port == 0 {
881- return Err ( Error :: config (
882- "docker compute driver requires a fixed non-zero gateway bind port" ,
883- ) ) ;
884- }
885884 let mut docker_config = docker_config. clone ( ) ;
886885 if docker_config. grpc_endpoint . trim ( ) . is_empty ( ) {
887886 docker_config. grpc_endpoint = default_docker_supervisor_grpc_endpoint (
@@ -947,6 +946,7 @@ impl DockerComputeDriver {
947946 allow_driver_config : docker_config. allow_driver_config ,
948947 resource_admission : docker_config. resource_admission . clone ( ) ,
949948 upstream_proxy : docker_config. upstream_proxy . clone ( ) ,
949+ proxy_ca_bundle : docker_config. proxy_ca_bundle . clone ( ) ,
950950 provider_spiffe_workload_api_socket : docker_config
951951 . provider_spiffe_workload_api_socket
952952 . clone ( ) ,
@@ -4713,11 +4713,35 @@ async fn docker_supervisor_bundle_archive(
47134713 & contents,
47144714 ) ?;
47154715 }
4716+ append_docker_proxy_ca_bundle ( & mut archive, config. proxy_ca_bundle . as_deref ( ) ) ?;
47164717 archive
47174718 . into_inner ( )
47184719 . map_err ( |error| Status :: internal ( format ! ( "finish Docker supervisor archive: {error}" ) ) )
47194720}
47204721
4722+ fn append_docker_proxy_ca_bundle (
4723+ archive : & mut tar:: Builder < Vec < u8 > > ,
4724+ path : Option < & Path > ,
4725+ ) -> Result < ( ) , Status > {
4726+ let Some ( path) = path else {
4727+ return Ok ( ( ) ) ;
4728+ } ;
4729+ let path = path
4730+ . to_str ( )
4731+ . ok_or_else ( || Status :: failed_precondition ( "proxy_ca_bundle must be valid UTF-8" ) ) ?;
4732+ let contents =
4733+ openshell_core:: driver_utils:: read_upstream_proxy_ca_bundle_file ( path, "proxy_ca_bundle" )
4734+ . map_err ( Status :: failed_precondition) ?;
4735+ append_docker_archive_file (
4736+ archive,
4737+ "upstream-proxy-ca-bundle.pem" ,
4738+ 0o644 ,
4739+ SUPERVISOR_UID ,
4740+ SUPERVISOR_GID ,
4741+ contents. as_bytes ( ) ,
4742+ )
4743+ }
4744+
47214745async fn refresh_docker_boundary_authentication (
47224746 sandbox_id : & str ,
47234747 config : & DockerDriverRuntimeConfig ,
@@ -5120,7 +5144,10 @@ async fn spawn_docker_control_process(
51205144 workspace_root,
51215145 format!( "--health-socket-path={SUPERVISOR_HEALTH_SOCKET_PATH}" ) ,
51225146 ] ;
5123- command. extend ( docker_upstream_proxy_cli_args ( & config. upstream_proxy ) ) ;
5147+ command. extend ( docker_upstream_proxy_cli_args (
5148+ & config. upstream_proxy ,
5149+ config. proxy_ca_bundle . is_some ( ) ,
5150+ ) ) ;
51245151 let mut supervisor_mounts = vec ! [
51255152 Mount {
51265153 target: Some ( BOUNDARY_MOUNT_PATH . to_string( ) ) ,
@@ -5871,7 +5898,30 @@ fn validate_docker_proxy_auth_file(config: &UpstreamProxyConfig) -> CoreResult<(
58715898 Ok ( ( ) )
58725899}
58735900
5874- fn docker_upstream_proxy_cli_args ( config : & UpstreamProxyConfig ) -> Vec < String > {
5901+ fn validate_docker_proxy_ca_bundle ( config : & DockerComputeConfig ) -> CoreResult < ( ) > {
5902+ let Some ( path) = config. proxy_ca_bundle . as_ref ( ) else {
5903+ return Ok ( ( ) ) ;
5904+ } ;
5905+ if path. as_os_str ( ) . is_empty ( ) {
5906+ return Err ( Error :: config ( "proxy_ca_bundle must not be empty when set" ) ) ;
5907+ }
5908+ if config. upstream_proxy . https_proxy . is_none ( ) {
5909+ return Err ( Error :: config (
5910+ "proxy_ca_bundle is set but no https_proxy is configured" ,
5911+ ) ) ;
5912+ }
5913+ let path = path
5914+ . to_str ( )
5915+ . ok_or_else ( || Error :: config ( "proxy_ca_bundle must be valid UTF-8" ) ) ?;
5916+ openshell_core:: driver_utils:: read_upstream_proxy_ca_bundle_file ( path, "proxy_ca_bundle" )
5917+ . map_err ( Error :: config) ?;
5918+ Ok ( ( ) )
5919+ }
5920+
5921+ fn docker_upstream_proxy_cli_args (
5922+ config : & UpstreamProxyConfig ,
5923+ proxy_ca_bundle_configured : bool ,
5924+ ) -> Vec < String > {
58755925 let mut args = Vec :: new ( ) ;
58765926 if let Some ( url) = config. https_proxy . as_ref ( ) {
58775927 args. extend ( [ "--upstream-proxy" . to_string ( ) , url. clone ( ) ] ) ;
@@ -5891,6 +5941,12 @@ fn docker_upstream_proxy_cli_args(config: &UpstreamProxyConfig) -> Vec<String> {
58915941 if config. proxy_connect_by_hostname == Some ( true ) {
58925942 args. push ( "--upstream-proxy-connect-by-hostname" . to_string ( ) ) ;
58935943 }
5944+ if proxy_ca_bundle_configured {
5945+ args. extend ( [
5946+ "--upstream-proxy-ca-bundle" . to_string ( ) ,
5947+ SUPERVISOR_PROXY_CA_BUNDLE_MOUNT_PATH . to_string ( ) ,
5948+ ] ) ;
5949+ }
58945950 args
58955951}
58965952
0 commit comments