@@ -16,27 +16,15 @@ use openshell_isolation_interface::contract::{
1616} ;
1717use openshell_sandbox_backend:: GPU_RESOURCE_CLAIM ;
1818use openshell_sandbox_backend:: boundary_protocol:: {
19- BoundaryConfig , BoundaryListener , FenceWireFormat , GatewayVerificationKey ,
20- SandboxRuntimeDescriptor , SandboxTlsClientConfig , SandboxTlsServerConfig , SandboxTransport ,
21- fence_wire_format,
19+ BoundaryConfig , BoundaryListener , GatewayVerificationKey , SandboxRuntimeDescriptor ,
20+ SandboxTlsClientConfig , SandboxTlsServerConfig , SandboxTransport ,
2221} ;
23- use serde:: de:: DeserializeOwned ;
24- use serde:: { Deserialize , Serialize } ;
25-
26- #[ derive( Deserialize , Serialize ) ]
27- #[ serde( tag = "backend" , rename_all = "kebab-case" , deny_unknown_fields) ]
28- enum LegacyDriverFenceEvidence {
29- Docker {
30- container_id : String ,
31- network_mode : String ,
32- unexpected_networks : Vec < String > ,
33- } ,
34- }
22+ use serde:: Serialize ;
3523
3624#[ derive( Serialize ) ]
3725struct DockerOuterFenceEvidence < ' a > {
3826 container_id : & ' a str ,
39- network_mode : & ' a str ,
27+ network_mode : & ' static str ,
4028 unexpected_networks : & ' a [ String ] ,
4129}
4230
@@ -70,127 +58,6 @@ impl DockerOuterFenceEvidence<'_> {
7058 }
7159}
7260
73- fn decode_fence_compatible < T : DeserializeOwned > (
74- encoded : & [ u8 ] ,
75- description : & str ,
76- ) -> Result < ( T , FenceWireFormat ) , BackendError > {
77- let mut value: serde_json:: Value = serde_json:: from_slice ( encoded)
78- . map_err ( |error| BackendError :: Descriptor ( format ! ( "decode {description}: {error}" ) ) ) ?;
79- let object = value. as_object_mut ( ) . ok_or_else ( || {
80- BackendError :: Descriptor ( format ! ( "decode {description}: expected a JSON object" ) )
81- } ) ?;
82- let format = fence_wire_format ( object, description) ?;
83- if format == FenceWireFormat :: LegacyDriverFence {
84- let generation = object
85- . get ( "generation" )
86- . and_then ( serde_json:: Value :: as_str)
87- . ok_or_else ( || {
88- BackendError :: Descriptor ( format ! (
89- "decode {description}: legacy bootstrap generation is missing"
90- ) )
91- } ) ?
92- . to_string ( ) ;
93- let legacy: LegacyDriverFenceEvidence = serde_json:: from_value (
94- object. remove ( "driver_fence" ) . expect ( "checked above" ) ,
95- )
96- . map_err ( |error| {
97- BackendError :: Descriptor ( format ! ( "decode {description} legacy driver fence: {error}" ) )
98- } ) ?;
99- let LegacyDriverFenceEvidence :: Docker {
100- container_id,
101- network_mode,
102- unexpected_networks,
103- } = legacy;
104- let projection = DockerOuterFenceEvidence {
105- container_id : & container_id,
106- network_mode : & network_mode,
107- unexpected_networks : & unexpected_networks,
108- }
109- . project ( & generation) ?;
110- object. insert (
111- "outer_fence" . to_string ( ) ,
112- serde_json:: to_value ( projection) . map_err ( |error| {
113- BackendError :: Descriptor ( format ! ( "encode migrated Docker outer fence: {error}" ) )
114- } ) ?,
115- ) ;
116- }
117- serde_json:: from_value ( value)
118- . map ( |decoded| ( decoded, format) )
119- . map_err ( |error| BackendError :: Descriptor ( format ! ( "decode {description}: {error}" ) ) )
120- }
121-
122- pub fn decode_boundary_config_compatible (
123- encoded : & [ u8 ] ,
124- ) -> Result < ( BoundaryConfig , FenceWireFormat ) , BackendError > {
125- decode_fence_compatible ( encoded, "Docker boundary config" )
126- }
127-
128- pub fn decode_runtime_descriptor_compatible (
129- encoded : & [ u8 ] ,
130- ) -> Result < ( SandboxRuntimeDescriptor , FenceWireFormat ) , BackendError > {
131- decode_fence_compatible ( encoded, "Docker runtime descriptor" )
132- }
133-
134- fn encode_fence_compatible < T : Serialize > (
135- value : & T ,
136- format : FenceWireFormat ,
137- description : & str ,
138- ) -> Result < Vec < u8 > , BackendError > {
139- let mut value = serde_json:: to_value ( value)
140- . map_err ( |error| BackendError :: Descriptor ( format ! ( "encode {description}: {error}" ) ) ) ?;
141- if format == FenceWireFormat :: LegacyDriverFence {
142- let object = value. as_object_mut ( ) . ok_or_else ( || {
143- BackendError :: Descriptor ( format ! ( "encode {description}: expected a JSON object" ) )
144- } ) ?;
145- let container_id = object
146- . get ( "resource_claims" )
147- . and_then ( serde_json:: Value :: as_object)
148- . and_then ( |claims| claims. get ( "docker.container_id" ) )
149- . and_then ( serde_json:: Value :: as_str)
150- . filter ( |container_id| !container_id. is_empty ( ) )
151- . ok_or_else ( || {
152- BackendError :: Descriptor ( format ! (
153- "encode {description}: Docker container resource claim is missing"
154- ) )
155- } ) ?
156- . to_string ( ) ;
157- if object. remove ( "outer_fence" ) . is_none ( ) {
158- return Err ( BackendError :: Descriptor ( format ! (
159- "encode {description}: outer fence projection is missing"
160- ) ) ) ;
161- }
162- object. insert (
163- "driver_fence" . to_string ( ) ,
164- serde_json:: to_value ( LegacyDriverFenceEvidence :: Docker {
165- container_id,
166- network_mode : "none" . to_string ( ) ,
167- unexpected_networks : Vec :: new ( ) ,
168- } )
169- . map_err ( |error| {
170- BackendError :: Descriptor ( format ! (
171- "encode {description} legacy driver fence: {error}"
172- ) )
173- } ) ?,
174- ) ;
175- }
176- serde_json:: to_vec ( & value)
177- . map_err ( |error| BackendError :: Descriptor ( format ! ( "encode {description}: {error}" ) ) )
178- }
179-
180- pub fn encode_boundary_config_compatible (
181- config : & BoundaryConfig ,
182- format : FenceWireFormat ,
183- ) -> Result < Vec < u8 > , BackendError > {
184- encode_fence_compatible ( config, format, "Docker boundary config" )
185- }
186-
187- pub fn encode_runtime_descriptor_compatible (
188- descriptor : & SandboxRuntimeDescriptor ,
189- format : FenceWireFormat ,
190- ) -> Result < Vec < u8 > , BackendError > {
191- encode_fence_compatible ( descriptor, format, "Docker runtime descriptor" )
192- }
193-
19461/// Driver-owned inputs that bind one Docker container to one boundary.
19562pub struct DockerBoundarySpec {
19663 pub boundary_id : String ,
@@ -276,12 +143,37 @@ impl DockerBoundarySpec {
276143mod tests {
277144 use super :: * ;
278145
279- fn provisioning ( ) -> DockerBoundaryProvisioning {
146+ #[ test]
147+ fn outer_fence_projection_rejects_each_missing_native_fact ( ) {
148+ let unexpected_networks = vec ! [ "bridge" . to_string( ) ] ;
149+ for evidence in [
150+ DockerOuterFenceEvidence {
151+ container_id : "" ,
152+ network_mode : "none" ,
153+ unexpected_networks : & [ ] ,
154+ } ,
155+ DockerOuterFenceEvidence {
156+ container_id : "container" ,
157+ network_mode : "bridge" ,
158+ unexpected_networks : & [ ] ,
159+ } ,
160+ DockerOuterFenceEvidence {
161+ container_id : "container" ,
162+ network_mode : "none" ,
163+ unexpected_networks : & unexpected_networks,
164+ } ,
165+ ] {
166+ assert ! ( evidence. project( "generation-1" ) . is_err( ) ) ;
167+ }
168+ }
169+
170+ #[ test]
171+ fn provisioning_binds_container_and_image_claims ( ) {
280172 let session_id = openshell_core:: SandboxSessionId :: new ( ) ;
281173 let tls =
282174 openshell_sandbox_backend:: boundary_protocol:: generate_sandbox_tls_material ( session_id)
283175 . unwrap ( ) ;
284- DockerBoundarySpec {
176+ let provisioned = DockerBoundarySpec {
285177 boundary_id : "sandbox-1" . to_string ( ) ,
286178 generation : "generation-1" . to_string ( ) ,
287179 session_id,
@@ -317,36 +209,7 @@ mod tests {
317209 child_env : HashMap :: new ( ) ,
318210 }
319211 . provision ( )
320- . unwrap ( )
321- }
322-
323- #[ test]
324- fn outer_fence_projection_rejects_each_missing_native_fact ( ) {
325- let unexpected_networks = vec ! [ "bridge" . to_string( ) ] ;
326- for evidence in [
327- DockerOuterFenceEvidence {
328- container_id : "" ,
329- network_mode : "none" ,
330- unexpected_networks : & [ ] ,
331- } ,
332- DockerOuterFenceEvidence {
333- container_id : "container" ,
334- network_mode : "bridge" ,
335- unexpected_networks : & [ ] ,
336- } ,
337- DockerOuterFenceEvidence {
338- container_id : "container" ,
339- network_mode : "none" ,
340- unexpected_networks : & unexpected_networks,
341- } ,
342- ] {
343- assert ! ( evidence. project( "generation-1" ) . is_err( ) ) ;
344- }
345- }
346-
347- #[ test]
348- fn provisioning_binds_container_and_image_claims ( ) {
349- let provisioned = provisioning ( ) ;
212+ . unwrap ( ) ;
350213
351214 assert_eq ! (
352215 provisioned. boundary_config. resource_claims,
@@ -372,36 +235,4 @@ mod tests {
372235 . is_ok( )
373236 ) ;
374237 }
375-
376- #[ test]
377- fn legacy_driver_fence_round_trips_through_current_projection ( ) {
378- let provisioned = provisioning ( ) ;
379- let boundary = encode_boundary_config_compatible (
380- & provisioned. boundary_config ,
381- FenceWireFormat :: LegacyDriverFence ,
382- )
383- . unwrap ( ) ;
384- let descriptor = encode_runtime_descriptor_compatible (
385- & provisioned. runtime_descriptor ,
386- FenceWireFormat :: LegacyDriverFence ,
387- )
388- . unwrap ( ) ;
389- for encoded in [ & boundary, & descriptor] {
390- let value: serde_json:: Value = serde_json:: from_slice ( encoded) . unwrap ( ) ;
391- assert ! ( value. get( "outer_fence" ) . is_none( ) ) ;
392- assert_eq ! ( value[ "driver_fence" ] [ "backend" ] , "docker" ) ;
393- assert_eq ! ( value[ "driver_fence" ] [ "container_id" ] , "sha256:container" ) ;
394- }
395- let ( decoded_boundary, boundary_format) =
396- decode_boundary_config_compatible ( & boundary) . unwrap ( ) ;
397- let ( decoded_descriptor, descriptor_format) =
398- decode_runtime_descriptor_compatible ( & descriptor) . unwrap ( ) ;
399- assert_eq ! ( boundary_format, FenceWireFormat :: LegacyDriverFence ) ;
400- assert_eq ! ( descriptor_format, FenceWireFormat :: LegacyDriverFence ) ;
401- assert_eq ! ( decoded_boundary. outer_fence, decoded_descriptor. outer_fence) ;
402- assert_eq ! (
403- decoded_boundary. outer_fence,
404- provisioned. boundary_config. outer_fence
405- ) ;
406- }
407238}
0 commit comments