Skip to content

Commit 4d6854a

Browse files
committed
feat(simulator): make report data patching configurable
1 parent ac418e0 commit 4d6854a

4 files changed

Lines changed: 81 additions & 11 deletions

File tree

guest-agent-simulator/dstack.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ data_disks = ["/"]
1818

1919
[default.core.simulator]
2020
attestation_file = "attestation.bin"
21+
patch_report_data = true
2122

2223
[internal-v0]
2324
address = "unix:./tappd.sock"

guest-agent-simulator/src/main.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ struct Args {
3636
#[derive(Debug, Clone, Deserialize)]
3737
struct SimulatorSettings {
3838
attestation_file: String,
39+
#[serde(default = "default_patch_report_data")]
40+
patch_report_data: bool,
3941
}
4042

4143
#[derive(Debug, Clone, Deserialize)]
@@ -47,14 +49,22 @@ struct SimulatorCoreConfig {
4749

4850
struct SimulatorPlatform {
4951
attestation: VersionedAttestation,
52+
patch_report_data: bool,
5053
}
5154

5255
impl SimulatorPlatform {
53-
fn new(attestation: VersionedAttestation) -> Self {
54-
Self { attestation }
56+
fn new(attestation: VersionedAttestation, patch_report_data: bool) -> Self {
57+
Self {
58+
attestation,
59+
patch_report_data,
60+
}
5561
}
5662
}
5763

64+
fn default_patch_report_data() -> bool {
65+
true
66+
}
67+
5868
impl PlatformBackend for SimulatorPlatform {
5969
fn attestation_for_info(&self) -> Result<Attestation> {
6070
Ok(simulator::simulated_info_attestation(&self.attestation))
@@ -64,17 +74,24 @@ impl PlatformBackend for SimulatorPlatform {
6474
Ok(simulator::simulated_certificate_attestation(
6575
&self.attestation,
6676
pubkey,
77+
self.patch_report_data,
6778
))
6879
}
6980

7081
fn quote_response(&self, report_data: [u8; 64], vm_config: &str) -> Result<GetQuoteResponse> {
71-
simulator::simulated_quote_response(&self.attestation, report_data, vm_config)
82+
simulator::simulated_quote_response(
83+
&self.attestation,
84+
report_data,
85+
vm_config,
86+
self.patch_report_data,
87+
)
7288
}
7389

7490
fn attest_response(&self, report_data: [u8; 64]) -> Result<AttestResponse> {
7591
Ok(simulator::simulated_attest_response(
7692
&self.attestation,
7793
report_data,
94+
self.patch_report_data,
7895
))
7996
}
8097

@@ -96,12 +113,24 @@ async fn main() -> Result<()> {
96113
.focus("core")
97114
.extract()
98115
.context("Failed to extract simulator core config")?;
99-
warn!(attestation_file = %sim_config.simulator.attestation_file, "starting dstack guest-agent simulator");
116+
warn!(
117+
attestation_file = %sim_config.simulator.attestation_file,
118+
patch_report_data = sim_config.simulator.patch_report_data,
119+
"starting dstack guest-agent simulator"
120+
);
121+
if sim_config.simulator.patch_report_data {
122+
warn!("simulator will rewrite report_data to match requests; quote verification may fail against the original fixture signature");
123+
} else {
124+
warn!("simulator will preserve fixture report_data; cert/key binding and requested report_data may not match");
125+
}
100126
let attestation =
101127
simulator::load_versioned_attestation(&sim_config.simulator.attestation_file)?;
102128
let state = AppState::new(
103129
sim_config.core,
104-
Arc::new(SimulatorPlatform::new(attestation)),
130+
Arc::new(SimulatorPlatform::new(
131+
attestation,
132+
sim_config.simulator.patch_report_data,
133+
)),
105134
)
106135
.await
107136
.context("Failed to create simulator app state")?;
@@ -118,7 +147,7 @@ mod tests {
118147
.join("../guest-agent/fixtures/attestation.bin"),
119148
)
120149
.expect("fixture attestation should load");
121-
SimulatorPlatform::new(fixture)
150+
SimulatorPlatform::new(fixture, true)
122151
}
123152

124153
#[test]
@@ -147,4 +176,21 @@ mod tests {
147176
let VersionedAttestation::V0 { attestation } = patched;
148177
assert_eq!(attestation.report_data, report_data);
149178
}
179+
180+
#[test]
181+
fn simulator_can_preserve_fixture_report_data() {
182+
let fixture = simulator::load_versioned_attestation(
183+
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
184+
.join("../guest-agent/fixtures/attestation.bin"),
185+
)
186+
.expect("fixture attestation should load");
187+
let original = fixture.clone().into_inner().report_data;
188+
let platform = SimulatorPlatform::new(fixture, false);
189+
let report_data = [0x5a; 64];
190+
let response = platform.attest_response(report_data).unwrap();
191+
let patched = VersionedAttestation::from_scale(&response.attestation).unwrap();
192+
let VersionedAttestation::V0 { attestation } = patched;
193+
assert_eq!(attestation.report_data, original);
194+
assert_ne!(attestation.report_data, report_data);
195+
}
150196
}

guest-agent-simulator/src/simulator.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use dstack_guest_agent_rpc::{AttestResponse, GetQuoteResponse};
99
use ra_rpc::Attestation;
1010
use ra_tls::attestation::{QuoteContentType, VersionedAttestation, TDX_QUOTE_REPORT_DATA_RANGE};
1111
use std::fs;
12+
use tracing::warn;
1213

1314
pub fn load_versioned_attestation(path: impl AsRef<Path>) -> Result<VersionedAttestation> {
1415
let path = path.as_ref();
@@ -26,8 +27,10 @@ pub fn simulated_quote_response(
2627
attestation: &VersionedAttestation,
2728
report_data: [u8; 64],
2829
vm_config: &str,
30+
patch_report_data: bool,
2931
) -> Result<GetQuoteResponse> {
30-
let VersionedAttestation::V0 { attestation } = patch_report_data(attestation, report_data);
32+
let VersionedAttestation::V0 { attestation } =
33+
maybe_patch_report_data(attestation, report_data, patch_report_data, "quote");
3134
let mut attestation = attestation;
3235
let Some(quote) = attestation.tdx_quote_mut() else {
3336
return Err(anyhow::anyhow!("Quote not found"));
@@ -45,9 +48,11 @@ pub fn simulated_quote_response(
4548
pub fn simulated_attest_response(
4649
attestation: &VersionedAttestation,
4750
report_data: [u8; 64],
51+
patch_report_data: bool,
4852
) -> AttestResponse {
4953
AttestResponse {
50-
attestation: patch_report_data(attestation, report_data).to_scale(),
54+
attestation: maybe_patch_report_data(attestation, report_data, patch_report_data, "attest")
55+
.to_scale(),
5156
}
5257
}
5358

@@ -58,23 +63,40 @@ pub fn simulated_info_attestation(attestation: &VersionedAttestation) -> Attesta
5863
pub fn simulated_certificate_attestation(
5964
attestation: &VersionedAttestation,
6065
pubkey: &[u8],
66+
patch_report_data: bool,
6167
) -> VersionedAttestation {
6268
let report_data = QuoteContentType::RaTlsCert.to_report_data(pubkey);
63-
patch_report_data(attestation, report_data)
69+
maybe_patch_report_data(
70+
attestation,
71+
report_data,
72+
patch_report_data,
73+
"certificate_attestation",
74+
)
6475
}
6576

66-
fn patch_report_data(
77+
fn maybe_patch_report_data(
6778
attestation: &VersionedAttestation,
6879
report_data: [u8; 64],
80+
patch_report_data: bool,
81+
context: &str,
6982
) -> VersionedAttestation {
83+
if !patch_report_data {
84+
warn!(
85+
context = context,
86+
requested_report_data = ?report_data,
87+
"simulator is preserving fixture report_data; returned attestation may not match the current request"
88+
);
89+
return attestation.clone();
90+
}
91+
7092
let VersionedAttestation::V0 { attestation } = attestation.clone();
7193
let mut attestation = attestation;
7294
attestation.report_data = report_data;
7395
if let Some(tdx_quote) = attestation.tdx_quote_mut() {
7496
if tdx_quote.quote.len() >= TDX_QUOTE_REPORT_DATA_RANGE.end {
7597
tdx_quote.quote[TDX_QUOTE_REPORT_DATA_RANGE].copy_from_slice(&report_data);
7698
} else {
77-
tracing::warn!(
99+
warn!(
78100
"TDX quote too short to patch report_data ({} < {})",
79101
tdx_quote.quote.len(),
80102
TDX_QUOTE_REPORT_DATA_RANGE.end

sdk/simulator/dstack.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ data_disks = ["/"]
1818

1919
[default.core.simulator]
2020
attestation_file = "attestation.bin"
21+
patch_report_data = true
2122

2223
[internal-v0]
2324
address = "unix:./tappd.sock"

0 commit comments

Comments
 (0)