@@ -7,6 +7,7 @@ use std::io::Write;
77use std:: process:: Stdio ;
88
99use openshell_e2e:: harness:: binary:: openshell_cmd;
10+ use openshell_e2e:: harness:: container:: is_e2e_driver;
1011use openshell_e2e:: harness:: sandbox:: SandboxGuard ;
1112use tempfile:: { Builder as TempFileBuilder , NamedTempFile } ;
1213use tokio:: io:: AsyncReadExt ;
@@ -184,7 +185,7 @@ binaries: [/usr/bin/bash]
184185 Ok ( file)
185186}
186187
187- fn write_binding_policy ( port : u16 ) -> Result < NamedTempFile , String > {
188+ fn write_binding_policy ( port : u16 , unbound_host : & str ) -> Result < NamedTempFile , String > {
188189 let mut file = NamedTempFile :: new ( ) . map_err ( |e| format ! ( "create binding policy: {e}" ) ) ?;
189190 let policy = format ! (
190191 r#"version: 1
@@ -211,7 +212,7 @@ network_policies:
211212 protocol: rest
212213 access: full
213214 enforcement: enforce
214- - host: host.docker.internal
215+ - host: {unbound_host}
215216 port: {port}
216217 path: /**
217218 protocol: rest
@@ -342,6 +343,11 @@ async fn sandbox_reaches_host_openshell_internal_via_host_gateway_alias() {
342343
343344#[ tokio:: test]
344345async fn static_provider_credentials_are_bound_to_profile_endpoints ( ) {
346+ let unbound_host = if is_e2e_driver ( "podman" ) {
347+ "host.containers.internal"
348+ } else {
349+ "host.docker.internal"
350+ } ;
345351 let server = HostServer :: start_with_auth_check ( "" , Some ( "Bearer e2e-bound-secret" ) )
346352 . await
347353 . expect ( "start credential echo server" ) ;
@@ -357,11 +363,11 @@ async fn static_provider_credentials_are_bound_to_profile_endpoints() {
357363 BINDING_PROFILE_B_ID ,
358364 "E2E static endpoint binding B" ,
359365 "BOUND_TOKEN_B" ,
360- "host.docker.internal" ,
366+ unbound_host ,
361367 server. port ,
362368 )
363369 . expect ( "write provider B binding profile" ) ;
364- let policy = write_binding_policy ( server. port ) . expect ( "write binding policy" ) ;
370+ let policy = write_binding_policy ( server. port , unbound_host ) . expect ( "write binding policy" ) ;
365371 let profile_a_path = profile_a. path ( ) . to_string_lossy ( ) . into_owned ( ) ;
366372 let profile_b_path = profile_b. path ( ) . to_string_lossy ( ) . into_owned ( ) ;
367373 let policy_path = policy. path ( ) . to_string_lossy ( ) . into_owned ( ) ;
@@ -420,9 +426,9 @@ http_request() {{
420426 exec 3>&- 3<&-
421427}}
422428http_request host.openshell.internal /allowed/check; allowed="$HTTP_BODY"
423- http_request host.docker.internal /allowed/check; host_denied="$HTTP_STATUS"
429+ http_request {unbound_host} /allowed/check; host_connect_exit=$? ; host_denied="$HTTP_STATUS"
424430http_request host.openshell.internal /other/check; path_denied="$HTTP_STATUS"
425- printf 'ALLOWED=%s HOST_DENIED=%s PATH_DENIED=%s\n' "$allowed" "$host_denied" "$path_denied"
431+ printf 'ALLOWED=%s HOST_DENIED=%s HOST_CONNECT_EXIT=%s PATH_DENIED=%s\n' "$allowed" "$host_denied" "$host_connect_exit " "$path_denied"
426432"# ,
427433 server. port
428434 ) ;
@@ -455,8 +461,15 @@ printf 'ALLOWED=%s HOST_DENIED=%s PATH_DENIED=%s\n' "$allowed" "$host_denied" "$
455461 "credential should resolve at the bound endpoint:\n {}\n logs:\n {logs}" ,
456462 guard. create_output,
457463 ) ;
464+ let host_denied_by_http = guard. create_output . contains ( "HOST_DENIED=403" ) ;
465+ let host_denied_by_podman_boundary = is_e2e_driver ( "podman" )
466+ && guard. create_output . contains ( "HOST_CONNECT_EXIT=1" )
467+ && guard. create_output . contains ( & format ! (
468+ "/dev/tcp/{unbound_host}/{}: Permission denied" ,
469+ server. port
470+ ) ) ;
458471 assert ! (
459- guard . create_output . contains ( "HOST_DENIED=403" ) ,
472+ host_denied_by_http || host_denied_by_podman_boundary ,
460473 "same placeholder must be denied at an unbound host:\n {}" ,
461474 guard. create_output
462475 ) ;
0 commit comments