@@ -66,6 +66,23 @@ impl AttestationType {
6666 AttestationType :: DcapTdx => "dcap-tdx" ,
6767 }
6868 }
69+
70+ /// Detect what platform we are on by attempting an attestation
71+ pub async fn detect ( ) -> Self {
72+ // First attempt azure, if the feature is present
73+ #[ cfg( feature = "azure" ) ]
74+ {
75+ if azure:: create_azure_attestation ( [ 0 ; 64 ] ) . await . is_ok ( ) {
76+ return AttestationType :: AzureTdx ;
77+ }
78+ }
79+ // Otherwise try DCAP quote - this internally checks that the quote provider is `tdx_guest`
80+ if configfs_tsm:: create_tdx_quote ( [ 0 ; 64 ] ) . is_ok ( ) {
81+ // TODO Possibly also check if it looks like we are on GCP (eg: hit metadata API)
82+ return AttestationType :: DcapTdx ;
83+ }
84+ AttestationType :: None
85+ }
6986}
7087
7188/// SCALE encode (used over the wire)
@@ -99,6 +116,25 @@ pub struct AttestationGenerator {
99116}
100117
101118impl AttestationGenerator {
119+ /// Create an [AttestationGenerator] detecting the attestation type if it is specified as 'auto'
120+ pub async fn new_with_detection (
121+ attestation_type_string : Option < String > ,
122+ dummy_dcap_url : Option < String > ,
123+ ) -> Result < Self , AttestationError > {
124+ let attestaton_type = if attestation_type_string. as_deref ( ) == Some ( "auto" ) {
125+ tracing:: info!( "Doing attestation type detection..." ) ;
126+ AttestationType :: detect ( ) . await
127+ } else {
128+ serde_json:: from_value ( serde_json:: Value :: String (
129+ attestation_type_string. unwrap_or ( "none" . to_string ( ) ) ,
130+ ) )
131+ . unwrap ( )
132+ } ;
133+ tracing:: info!( "Local platform: {attestaton_type}" ) ;
134+
135+ Self :: new ( attestaton_type, dummy_dcap_url)
136+ }
137+
102138 pub fn new (
103139 attestation_type : AttestationType ,
104140 dummy_dcap_url : Option < String > ,
@@ -116,6 +152,8 @@ impl AttestationGenerator {
116152 }
117153 }
118154
155+ /// Create an [AttestationGenerator] without a given dummy DCAP url - meaning Dummy attestation
156+ /// type will not be possible
119157 pub fn new_not_dummy ( attestation_type : AttestationType ) -> Result < Self , AttestationError > {
120158 if attestation_type == AttestationType :: Dummy {
121159 return Err ( AttestationError :: DummyUrl ) ;
@@ -127,6 +165,7 @@ impl AttestationGenerator {
127165 } )
128166 }
129167
168+ /// Create a dummy [AttestationGenerator]
130169 pub fn new_dummy ( dummy_dcap_url : Option < String > ) -> Result < Self , AttestationError > {
131170 match dummy_dcap_url {
132171 Some ( url) => {
@@ -181,6 +220,9 @@ impl AttestationGenerator {
181220 }
182221 }
183222
223+ /// Generate a dummy attestaion by using an external service for the attestation generation
224+ ///
225+ /// This is for testing only
184226 async fn generate_dummy_attestation (
185227 & self ,
186228 input_data : [ u8 ; 64 ] ,
@@ -351,3 +393,14 @@ pub enum AttestationError {
351393 #[ error( "Dummy server: {0}" ) ]
352394 DummyServer ( String ) ,
353395}
396+
397+ #[ cfg( test) ]
398+ mod tests {
399+ use super :: * ;
400+
401+ #[ tokio:: test]
402+ async fn attestation_detection_does_not_panic ( ) {
403+ // We dont enforce what platform the test is run on, only that the function does not panic
404+ let _ = AttestationGenerator :: new_with_detection ( Some ( "auto" . to_string ( ) ) , None ) . await ;
405+ }
406+ }
0 commit comments