@@ -774,7 +774,7 @@ fn verify_manifest_version(app_compose: &AppCompose) -> Result<u32> {
774774 Ok ( manifest_version)
775775}
776776
777- fn verify_app_compose_policy ( app_compose : & AppCompose ) -> Result < ( ) > {
777+ fn verify_app_compose_policy ( app_compose : & AppCompose , sys_config : & SysConfig ) -> Result < ( ) > {
778778 verify_manifest_feature_requirements ( app_compose) ?;
779779 let Some ( requirements) = app_compose. requirements . as_ref ( ) else {
780780 return Ok ( ( ) ) ;
@@ -789,9 +789,18 @@ fn verify_app_compose_policy(app_compose: &AppCompose) -> Result<()> {
789789 bail ! ( "Unsupported attestation platform: requirements.platforms is empty" ) ;
790790 }
791791 let current_platform =
792- AttestationMode :: detect ( ) . context ( "Failed to detect current attestation platform" ) ?;
792+ AttestationMode :: detect ( ) . context ( "failed to detect current attestation platform" ) ?;
793793 verify_platform_requirements ( app_compose, current_platform) ?;
794794 }
795+ if requirements. tdx_measure_acpi_tables . is_some ( ) {
796+ let current_platform =
797+ AttestationMode :: detect ( ) . context ( "failed to detect current attestation platform" ) ?;
798+ verify_tdx_measure_acpi_tables_requirement (
799+ app_compose,
800+ & sys_config. vm_config ,
801+ current_platform,
802+ ) ?;
803+ }
795804 Ok ( ( ) )
796805}
797806
@@ -867,6 +876,41 @@ fn format_requirement_platforms(platforms: &[String]) -> String {
867876 platforms. join ( ", " )
868877}
869878
879+ fn verify_tdx_measure_acpi_tables_requirement (
880+ app_compose : & AppCompose ,
881+ vm_config : & str ,
882+ current_platform : AttestationMode ,
883+ ) -> Result < ( ) > {
884+ let Some ( measure_acpi_tables) = app_compose
885+ . requirements
886+ . as_ref ( )
887+ . and_then ( |requirements| requirements. tdx_measure_acpi_tables )
888+ else {
889+ return Ok ( ( ) ) ;
890+ } ;
891+ if current_platform != AttestationMode :: DstackTdx {
892+ return Ok ( ( ) ) ;
893+ }
894+ let vm_config: dstack_types:: VmConfig = serde_json:: from_str ( vm_config)
895+ . context ( "failed to parse vm_config for requirements.tdx_measure_acpi_tables" ) ?;
896+ let uses_lite = vm_config. tdx_attestation_variant . is_lite ( ) ;
897+ if measure_acpi_tables && uses_lite {
898+ bail ! (
899+ "unsupported TDX attestation mode: requirements.tdx_measure_acpi_tables=true requires ACPI table measurement"
900+ ) ;
901+ }
902+ if !measure_acpi_tables && !uses_lite {
903+ bail ! (
904+ "unsupported TDX attestation mode: requirements.tdx_measure_acpi_tables=false requires TDX lite attestation"
905+ ) ;
906+ }
907+ info ! (
908+ "tdx ACPI table measurement requirement satisfied: measure_acpi_tables={}" ,
909+ measure_acpi_tables
910+ ) ;
911+ Ok ( ( ) )
912+ }
913+
870914fn read_current_os_version ( ) -> Result < String > {
871915 const OS_RELEASE_PATHS : & [ & str ] = & [ "/etc/os-release" , "/usr/lib/os-release" ] ;
872916 for path in OS_RELEASE_PATHS {
@@ -930,7 +974,7 @@ pub async fn cmd_sys_setup(args: SetupArgs) -> Result<()> {
930974}
931975
932976async fn do_sys_setup ( stage0 : Stage0 < ' _ > ) -> Result < ( ) > {
933- verify_app_compose_policy ( & stage0. shared . app_compose )
977+ verify_app_compose_policy ( & stage0. shared . app_compose , & stage0 . shared . sys_config )
934978 . context ( "Failed to verify app-compose policy" ) ?;
935979 if stage0. shared . app_compose . secure_time {
936980 info ! ( "Waiting for the system time to be synchronized" ) ;
@@ -2198,6 +2242,70 @@ fn test_platform_requirements_reject_invalid_platform_value() {
21982242 . contains( "Invalid requirements.platforms[0]" ) ) ;
21992243}
22002244
2245+ #[ test]
2246+ fn test_tdx_measure_acpi_tables_requirement_matches_vm_config ( ) {
2247+ let app_compose: AppCompose = serde_json:: from_value ( serde_json:: json!( {
2248+ "manifest_version" : "3" ,
2249+ "name" : "test" ,
2250+ "runner" : "docker-compose" ,
2251+ "requirements" : {
2252+ "tdx_measure_acpi_tables" : true
2253+ }
2254+ } ) )
2255+ . unwrap ( ) ;
2256+ verify_tdx_measure_acpi_tables_requirement ( & app_compose, r#"{}"# , AttestationMode :: DstackTdx )
2257+ . unwrap ( ) ;
2258+ let err = verify_tdx_measure_acpi_tables_requirement (
2259+ & app_compose,
2260+ r#"{"tdx_attestation_variant":"lite"}"# ,
2261+ AttestationMode :: DstackTdx ,
2262+ )
2263+ . unwrap_err ( ) ;
2264+ assert ! ( err. to_string( ) . contains( "tdx_measure_acpi_tables=true" ) ) ;
2265+
2266+ let app_compose: AppCompose = serde_json:: from_value ( serde_json:: json!( {
2267+ "manifest_version" : "3" ,
2268+ "name" : "test" ,
2269+ "runner" : "docker-compose" ,
2270+ "requirements" : {
2271+ "tdx_measure_acpi_tables" : false
2272+ }
2273+ } ) )
2274+ . unwrap ( ) ;
2275+ verify_tdx_measure_acpi_tables_requirement (
2276+ & app_compose,
2277+ r#"{"tdx_attestation_variant":"lite"}"# ,
2278+ AttestationMode :: DstackTdx ,
2279+ )
2280+ . unwrap ( ) ;
2281+ let err = verify_tdx_measure_acpi_tables_requirement (
2282+ & app_compose,
2283+ r#"{}"# ,
2284+ AttestationMode :: DstackTdx ,
2285+ )
2286+ . unwrap_err ( ) ;
2287+ assert ! ( err. to_string( ) . contains( "tdx_measure_acpi_tables=false" ) ) ;
2288+ }
2289+
2290+ #[ test]
2291+ fn test_tdx_measure_acpi_tables_requirement_ignored_on_non_tdx ( ) {
2292+ let app_compose: AppCompose = serde_json:: from_value ( serde_json:: json!( {
2293+ "manifest_version" : "3" ,
2294+ "name" : "test" ,
2295+ "runner" : "docker-compose" ,
2296+ "requirements" : {
2297+ "tdx_measure_acpi_tables" : true
2298+ }
2299+ } ) )
2300+ . unwrap ( ) ;
2301+ verify_tdx_measure_acpi_tables_requirement (
2302+ & app_compose,
2303+ r#"{"tdx_attestation_variant":"lite"}"# ,
2304+ AttestationMode :: DstackAmdSevSnp ,
2305+ )
2306+ . unwrap ( ) ;
2307+ }
2308+
22012309#[ test]
22022310fn test_os_release_value_parses_quoted_version_id ( ) {
22032311 let content = r#"
0 commit comments