Skip to content

Commit 22b74ff

Browse files
committed
refactor(simulator): move simulator helpers out of guest-agent crate
1 parent 1b70779 commit 22b74ff

6 files changed

Lines changed: 108 additions & 93 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

guest-agent-simulator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ path = "src/main.rs"
1717
anyhow.workspace = true
1818
clap.workspace = true
1919
serde.workspace = true
20+
serde_json.workspace = true
2021
tracing.workspace = true
2122
tracing-subscriber.workspace = true
2223
rocket.workspace = true

guest-agent-simulator/src/main.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22
//
33
// SPDX-License-Identifier: Apache-2.0
44

5+
mod simulator;
6+
57
use std::sync::Arc;
68

79
use anyhow::{bail, Context, Result};
810
use clap::Parser;
911
use dstack_guest_agent::{
10-
backend::{
11-
load_versioned_attestation, simulated_attest_response,
12-
simulated_certificate_attestation, simulated_info_attestation,
13-
simulated_quote_response, PlatformBackend,
14-
},
12+
backend::PlatformBackend,
1513
config::{self, Config},
1614
AppState, run_server,
1715
};
@@ -58,20 +56,20 @@ impl SimulatorPlatform {
5856
}
5957

6058
impl PlatformBackend for SimulatorPlatform {
61-
fn attestation_for_info(&self) -> Result<Option<Attestation>> {
62-
Ok(Some(simulated_info_attestation(&self.attestation)))
59+
fn attestation_for_info(&self) -> Result<Attestation> {
60+
Ok(simulator::simulated_info_attestation(&self.attestation))
6361
}
6462

6563
fn certificate_attestation(&self, pubkey: &[u8]) -> Result<VersionedAttestation> {
66-
Ok(simulated_certificate_attestation(&self.attestation, pubkey))
64+
Ok(simulator::simulated_certificate_attestation(&self.attestation, pubkey))
6765
}
6866

6967
fn quote_response(&self, report_data: [u8; 64], vm_config: &str) -> Result<GetQuoteResponse> {
70-
simulated_quote_response(&self.attestation, report_data, vm_config)
68+
simulator::simulated_quote_response(&self.attestation, report_data, vm_config)
7169
}
7270

7371
fn attest_response(&self, _report_data: [u8; 64]) -> Result<AttestResponse> {
74-
Ok(simulated_attest_response(&self.attestation))
72+
Ok(simulator::simulated_attest_response(&self.attestation))
7573
}
7674

7775
fn emit_event(&self, event: &str, _payload: &[u8]) -> Result<()> {
@@ -93,7 +91,7 @@ async fn main() -> Result<()> {
9391
.extract()
9492
.context("Failed to extract simulator core config")?;
9593
warn!(attestation_file = %sim_config.simulator.attestation_file, "starting dstack guest-agent simulator");
96-
let attestation = load_versioned_attestation(&sim_config.simulator.attestation_file)?;
94+
let attestation = simulator::load_versioned_attestation(&sim_config.simulator.attestation_file)?;
9795
let state = AppState::new(sim_config.core, Arc::new(SimulatorPlatform::new(attestation)))
9896
.await
9997
.context("Failed to create simulator app state")?;
@@ -106,7 +104,7 @@ mod tests {
106104
use super::*;
107105

108106
fn load_fixture_platform() -> SimulatorPlatform {
109-
let fixture = load_versioned_attestation(
107+
let fixture = simulator::load_versioned_attestation(
110108
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../guest-agent/fixtures/attestation.bin"),
111109
)
112110
.expect("fixture attestation should load");
@@ -125,6 +123,6 @@ mod tests {
125123
let platform = load_fixture_platform();
126124
let cert_attestation = platform.certificate_attestation(b"test-public-key").unwrap();
127125
assert!(cert_attestation.decode_app_info(false).is_ok());
128-
assert!(platform.attestation_for_info().unwrap().is_some());
126+
let _ = platform.attestation_for_info().unwrap();
129127
}
130128
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
use std::path::Path;
6+
7+
use anyhow::{Context, Result};
8+
use dstack_guest_agent_rpc::{AttestResponse, GetQuoteResponse};
9+
use std::fs;
10+
use ra_rpc::Attestation;
11+
use ra_tls::attestation::{
12+
QuoteContentType, VersionedAttestation, TDX_QUOTE_REPORT_DATA_RANGE,
13+
};
14+
15+
pub fn load_versioned_attestation(path: impl AsRef<Path>) -> Result<VersionedAttestation> {
16+
let path = path.as_ref();
17+
let attestation_bytes = fs::read(path).with_context(|| {
18+
format!(
19+
"Failed to read simulator attestation file: {}",
20+
path.display()
21+
)
22+
})?;
23+
VersionedAttestation::from_scale(&attestation_bytes)
24+
.context("Failed to decode simulator attestation")
25+
}
26+
27+
pub fn simulated_quote_response(
28+
attestation: &VersionedAttestation,
29+
report_data: [u8; 64],
30+
vm_config: &str,
31+
) -> Result<GetQuoteResponse> {
32+
let VersionedAttestation::V0 { attestation } = attestation.clone();
33+
let mut attestation = attestation;
34+
let Some(quote) = attestation.tdx_quote_mut() else {
35+
return Err(anyhow::anyhow!("Quote not found"));
36+
};
37+
38+
quote.quote[TDX_QUOTE_REPORT_DATA_RANGE].copy_from_slice(&report_data);
39+
Ok(GetQuoteResponse {
40+
quote: quote.quote.to_vec(),
41+
event_log: serde_json::to_string(&quote.event_log)
42+
.context("Failed to serialize event log")?,
43+
report_data: report_data.to_vec(),
44+
vm_config: vm_config.to_string(),
45+
})
46+
}
47+
48+
pub fn simulated_attest_response(attestation: &VersionedAttestation) -> AttestResponse {
49+
AttestResponse {
50+
attestation: attestation.to_scale(),
51+
}
52+
}
53+
54+
pub fn simulated_info_attestation(attestation: &VersionedAttestation) -> Attestation {
55+
attestation.clone().into_inner()
56+
}
57+
58+
pub fn simulated_certificate_attestation(
59+
attestation: &VersionedAttestation,
60+
pubkey: &[u8],
61+
) -> VersionedAttestation {
62+
let mut attestation = attestation.clone();
63+
let report_data = QuoteContentType::RaTlsCert.to_report_data(pubkey);
64+
attestation.set_report_data(report_data);
65+
attestation
66+
}

guest-agent/src/backend.rs

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,14 @@
22
//
33
// SPDX-License-Identifier: Apache-2.0
44

5-
use std::path::Path;
6-
75
use anyhow::{Context, Result};
86
use dstack_attest::emit_runtime_event;
97
use dstack_guest_agent_rpc::{AttestResponse, GetQuoteResponse};
10-
use fs_err as fs;
118
use ra_rpc::Attestation;
12-
use ra_tls::attestation::{
13-
QuoteContentType, VersionedAttestation, TDX_QUOTE_REPORT_DATA_RANGE,
14-
};
9+
use ra_tls::attestation::{QuoteContentType, VersionedAttestation};
1510

1611
pub trait PlatformBackend: Send + Sync {
17-
fn attestation_for_info(&self) -> Result<Option<Attestation>>;
12+
fn attestation_for_info(&self) -> Result<Attestation>;
1813
fn certificate_attestation(&self, pubkey: &[u8]) -> Result<VersionedAttestation>;
1914
fn quote_response(&self, report_data: [u8; 64], vm_config: &str) -> Result<GetQuoteResponse>;
2015
fn attest_response(&self, report_data: [u8; 64]) -> Result<AttestResponse>;
@@ -25,8 +20,8 @@ pub trait PlatformBackend: Send + Sync {
2520
pub struct RealPlatform;
2621

2722
impl PlatformBackend for RealPlatform {
28-
fn attestation_for_info(&self) -> Result<Option<Attestation>> {
29-
Ok(Attestation::local().ok())
23+
fn attestation_for_info(&self) -> Result<Attestation> {
24+
Attestation::local().context("Failed to get local attestation")
3025
}
3126

3227
fn certificate_attestation(&self, pubkey: &[u8]) -> Result<VersionedAttestation> {
@@ -59,56 +54,3 @@ impl PlatformBackend for RealPlatform {
5954
emit_runtime_event(event, payload)
6055
}
6156
}
62-
63-
pub fn load_versioned_attestation(path: impl AsRef<Path>) -> Result<VersionedAttestation> {
64-
let path = path.as_ref();
65-
let attestation_bytes = fs::read(path).with_context(|| {
66-
format!(
67-
"Failed to read simulator attestation file: {}",
68-
path.display()
69-
)
70-
})?;
71-
VersionedAttestation::from_scale(&attestation_bytes)
72-
.context("Failed to decode simulator attestation")
73-
}
74-
75-
pub fn simulated_quote_response(
76-
attestation: &VersionedAttestation,
77-
report_data: [u8; 64],
78-
vm_config: &str,
79-
) -> Result<GetQuoteResponse> {
80-
let VersionedAttestation::V0 { attestation } = attestation.clone();
81-
let mut attestation = attestation;
82-
let Some(quote) = attestation.tdx_quote_mut() else {
83-
return Err(anyhow::anyhow!("Quote not found"));
84-
};
85-
86-
quote.quote[TDX_QUOTE_REPORT_DATA_RANGE].copy_from_slice(&report_data);
87-
Ok(GetQuoteResponse {
88-
quote: quote.quote.to_vec(),
89-
event_log: serde_json::to_string(&quote.event_log)
90-
.context("Failed to serialize event log")?,
91-
report_data: report_data.to_vec(),
92-
vm_config: vm_config.to_string(),
93-
})
94-
}
95-
96-
pub fn simulated_attest_response(attestation: &VersionedAttestation) -> AttestResponse {
97-
AttestResponse {
98-
attestation: attestation.to_scale(),
99-
}
100-
}
101-
102-
pub fn simulated_info_attestation(attestation: &VersionedAttestation) -> Attestation {
103-
attestation.clone().into_inner()
104-
}
105-
106-
pub fn simulated_certificate_attestation(
107-
attestation: &VersionedAttestation,
108-
pubkey: &[u8],
109-
) -> VersionedAttestation {
110-
let mut attestation = attestation.clone();
111-
let report_data = QuoteContentType::RaTlsCert.to_report_data(pubkey);
112-
attestation.set_report_data(report_data);
113-
attestation
114-
}

guest-agent/src/rpc_service.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct AppStateInner {
6262
}
6363

6464
impl AppStateInner {
65-
fn info_attestation(&self) -> Result<Option<ra_rpc::Attestation>> {
65+
fn info_attestation(&self) -> Result<ra_rpc::Attestation> {
6666
self.platform.attestation_for_info()
6767
}
6868

@@ -178,9 +178,7 @@ pub struct InternalRpcHandler {
178178

179179
pub async fn get_info(state: &AppState, external: bool) -> Result<AppInfo> {
180180
let hide_tcb_info = external && !state.config().app_compose.public_tcbinfo;
181-
let Some(attestation) = state.inner.info_attestation()? else {
182-
return Ok(AppInfo::default());
183-
};
181+
let attestation = state.inner.info_attestation()?;
184182
let app_info = attestation
185183
.decode_app_info(false)
186184
.context("Failed to decode app info")?;
@@ -651,14 +649,7 @@ impl RpcCall<AppState> for ExternalRpcHandler {
651649
#[cfg(test)]
652650
mod tests {
653651
use super::*;
654-
use crate::{
655-
backend::{
656-
load_versioned_attestation, simulated_attest_response,
657-
simulated_certificate_attestation, simulated_info_attestation,
658-
simulated_quote_response, PlatformBackend,
659-
},
660-
config::{AppComposeWrapper, Config},
661-
};
652+
use crate::{backend::PlatformBackend, config::{AppComposeWrapper, Config}};
662653
use dstack_guest_agent_rpc::{GetAttestationForAppKeyRequest, SignRequest};
663654
use ra_tls::attestation::VersionedAttestation;
664655
use dstack_types::{AppCompose, AppKeys, KeyProvider};
@@ -807,24 +798,40 @@ pNs85uhOZE8z2jr8Pg==
807798
}
808799

809800
impl PlatformBackend for TestSimulatorPlatform {
810-
fn attestation_for_info(&self) -> Result<Option<ra_rpc::Attestation>> {
811-
Ok(Some(simulated_info_attestation(&self.attestation)))
801+
fn attestation_for_info(&self) -> Result<ra_rpc::Attestation> {
802+
Ok(self.attestation.clone().into_inner())
812803
}
813804

814805
fn certificate_attestation(&self, pubkey: &[u8]) -> Result<VersionedAttestation> {
815-
Ok(simulated_certificate_attestation(&self.attestation, pubkey))
806+
let mut attestation = self.attestation.clone();
807+
let report_data = ra_tls::attestation::QuoteContentType::RaTlsCert.to_report_data(pubkey);
808+
attestation.set_report_data(report_data);
809+
Ok(attestation)
816810
}
817811

818812
fn quote_response(
819813
&self,
820814
report_data: [u8; 64],
821815
vm_config: &str,
822816
) -> Result<GetQuoteResponse> {
823-
simulated_quote_response(&self.attestation, report_data, vm_config)
817+
let ra_tls::attestation::VersionedAttestation::V0 { attestation } = self.attestation.clone();
818+
let mut attestation = attestation;
819+
let Some(quote) = attestation.tdx_quote_mut() else {
820+
return Err(anyhow::anyhow!("Quote not found"));
821+
};
822+
quote.quote[ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE].copy_from_slice(&report_data);
823+
Ok(GetQuoteResponse {
824+
quote: quote.quote.to_vec(),
825+
event_log: serde_json::to_string(&quote.event_log).context("Failed to serialize event log")?,
826+
report_data: report_data.to_vec(),
827+
vm_config: vm_config.to_string(),
828+
})
824829
}
825830

826831
fn attest_response(&self, _report_data: [u8; 64]) -> Result<AttestResponse> {
827-
Ok(simulated_attest_response(&self.attestation))
832+
Ok(AttestResponse {
833+
attestation: self.attestation.to_scale(),
834+
})
828835
}
829836

830837
fn emit_event(&self, _event: &str, _payload: &[u8]) -> Result<()> {
@@ -839,7 +846,7 @@ pNs85uhOZE8z2jr8Pg==
839846
cert_client: dummy_cert_client,
840847
demo_cert: RwLock::new(String::new()),
841848
platform: Arc::new(TestSimulatorPlatform {
842-
attestation: load_versioned_attestation(temp_attestation_file.path()).unwrap(),
849+
attestation: VersionedAttestation::from_scale(&std::fs::read(temp_attestation_file.path()).unwrap()).unwrap(),
843850
}),
844851
};
845852

0 commit comments

Comments
 (0)