Skip to content

Commit c9191c9

Browse files
authored
Merge pull request #768 from Dstack-TEE/remove/guest-agent-emit-event
guest-agent: remove EmitEvent API
2 parents e5f138c + 342276f commit c9191c9

19 files changed

Lines changed: 12 additions & 297 deletions

File tree

docs/native-tee-interfaces.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,4 @@ For configfs-tsm, permissions can be more provider-specific. If your main proces
144144

145145
On TDX, RTMR3 is an append-only runtime measurement register. It is useful when a launcher measures code or configuration first, then hands permission and execution to the measured code.
146146

147-
Use `/EmitEvent` through `/var/run/dstack.sock` when you want dstack's event log and verifier to replay an application runtime measurement. If your application extends RTMR3 directly through native interfaces, your application owns the event-log story for those extensions.
147+
dstack itself extends RTMR3 during guest boot (compose-hash, key-provider, instance-id, and related runtime events). Applications that need additional runtime measurements should extend RTMR3 through the native TDX / TSM measurement interfaces documented above and own the event-log story for those extensions.

docs/security/security-model.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ dstack replays an event log only for RTMR3. RTMR0-2 (and MRTD) are not replayed
166166

167167
This is also reflected at the source: the event log shipped alongside an attestation is stripped down to RTMR3 entries before it is embedded. `VersionedAttestation::into_stripped()` keeps only events with `imr == 3` (see `dstack-attest/src/attestation.rs`), and verification only ever replays those runtime events against `rt_mr3` (`verify_tdx_quote_with_events` / `decode_mr_tdx_from_quote`).
168168

169-
The reason boot-time event log entries (RTMR0-2) are dropped is that **nothing downstream consumes them**. Verification recomputes the OS-layer measurements directly from the signed `rt_mr0/1/2` values and compares them to independently reproduced expected measurements, so the corresponding boot event log would be redundant. Keeping it would only bloat the RA-TLS certificate and expose extra detail without adding any verification capability. RTMR3, by contrast, is runtime-extended (compose-hash, key-provider, instance-id, and application-emitted events), so its event log is the only one with a real consumer — the replay that proves what was extended into RTMR3.
169+
The reason boot-time event log entries (RTMR0-2) are dropped is that **nothing downstream consumes them**. Verification recomputes the OS-layer measurements directly from the signed `rt_mr0/1/2` values and compares them to independently reproduced expected measurements, so the corresponding boot event log would be redundant. Keeping it would only bloat the RA-TLS certificate and expose extra detail without adding any verification capability. RTMR3, by contrast, is runtime-extended (compose-hash, key-provider, instance-id, and other guest boot events), so its event log is the only one with a real consumer — the replay that proves what was extended into RTMR3.
170170

171171
### Why TDX lite mode does not validate ACPI table contents
172172

dstack-attest/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ mod v1;
2424
/// Appending to the event log and extending RTMR3 must happen atomically as a
2525
/// unit: the order of log entries has to match the order of RTMR extensions,
2626
/// otherwise the RTMR replay performed during quote verification will not
27-
/// reproduce the measured value. Concurrent callers (e.g. multiple
28-
/// `emit_event` RPCs hitting the guest-agent at once) would otherwise be able
27+
/// reproduce the measured value. Concurrent callers would otherwise be able
2928
/// to interleave their log writes and `extend_rtmr` calls.
3029
static EMIT_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
3130

guest-agent-simulator/src/main.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod simulator;
66

77
use std::sync::Arc;
88

9-
use anyhow::{bail, Context, Result};
9+
use anyhow::{Context, Result};
1010
use clap::Parser;
1111
use dstack_guest_agent::{
1212
backend::PlatformBackend,
@@ -89,10 +89,6 @@ impl PlatformBackend for SimulatorPlatform {
8989
fn attest_response(&self, report_data: [u8; 64]) -> Result<AttestResponse> {
9090
simulator::simulated_attest_response(&self.attestation, report_data, self.patch_report_data)
9191
}
92-
93-
fn emit_event(&self, event: &str, _payload: &[u8]) -> Result<()> {
94-
bail!("runtime event emission is unavailable in simulator mode: {event}")
95-
}
9692
}
9793

9894
#[rocket::main]
@@ -145,13 +141,6 @@ mod tests {
145141
SimulatorPlatform::new(fixture, true)
146142
}
147143

148-
#[test]
149-
fn simulator_rejects_runtime_event_emission() {
150-
let platform = load_fixture_platform();
151-
let err = platform.emit_event("test.event", b"payload").unwrap_err();
152-
assert!(err.to_string().contains("unavailable in simulator mode"));
153-
}
154-
155144
#[test]
156145
fn simulator_provides_certificate_attestation() {
157146
let platform = load_fixture_platform();

guest-agent/rpc/proto/agent_rpc.proto

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ service DstackGuest {
5050
// Returns a dstack-defined attestation format that supports different attestation modes across platforms.
5151
rpc Attest(RawQuoteArgs) returns (AttestResponse) {}
5252

53-
// Emit an event. This extends the event to RTMR3 on TDX platform.
54-
rpc EmitEvent(EmitEventArgs) returns (google.protobuf.Empty) {}
55-
5653
// Get app info
5754
rpc Info(google.protobuf.Empty) returns (AppInfo) {}
5855

@@ -205,13 +202,6 @@ message GetQuoteResponse {
205202
bytes attestation = 5;
206203
}
207204

208-
message EmitEventArgs {
209-
// The event name
210-
string event = 1;
211-
// The event data
212-
bytes payload = 2;
213-
}
214-
215205
// The request to derive a key
216206
message AppInfo {
217207
// App ID

guest-agent/src/backend.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// SPDX-License-Identifier: Apache-2.0
44

55
use anyhow::{Context, Result};
6-
use dstack_attest::emit_runtime_event;
76
use dstack_guest_agent_rpc::{AttestResponse, GetQuoteResponse};
87
use ra_tls::attestation::Attestation;
98
use ra_tls::attestation::{QuoteContentType, VersionedAttestation};
@@ -13,7 +12,6 @@ pub trait PlatformBackend: Send + Sync {
1312
fn certificate_attestation(&self, pubkey: &[u8]) -> Result<VersionedAttestation>;
1413
fn quote_response(&self, report_data: [u8; 64], vm_config: &str) -> Result<GetQuoteResponse>;
1514
fn attest_response(&self, report_data: [u8; 64]) -> Result<AttestResponse>;
16-
fn emit_event(&self, event: &str, payload: &[u8]) -> Result<()>;
1715
}
1816

1917
#[derive(Debug, Default)]
@@ -62,8 +60,4 @@ impl PlatformBackend for RealPlatform {
6260
attestation: attestation.into_versioned().to_bytes()?,
6361
})
6462
}
65-
66-
fn emit_event(&self, event: &str, payload: &[u8]) -> Result<()> {
67-
emit_runtime_event(event, payload)
68-
}
6963
}

guest-agent/src/rpc_service.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ use dstack_guest_agent_rpc::{
1111
dstack_guest_server::{DstackGuestRpc, DstackGuestServer},
1212
tappd_server::{TappdRpc, TappdServer},
1313
worker_server::{WorkerRpc, WorkerServer},
14-
AppInfo, AttestResponse, DeriveK256KeyResponse, DeriveKeyArgs, EmitEventArgs,
15-
GetAttestationForAppKeyRequest, GetKeyArgs, GetKeyResponse, GetQuoteResponse, GetTlsKeyArgs,
16-
GetTlsKeyResponse, RawQuoteArgs, SignRequest, SignResponse, TdxQuoteArgs, TdxQuoteResponse,
17-
VerifyRequest, VerifyResponse, WorkerVersion,
14+
AppInfo, AttestResponse, DeriveK256KeyResponse, DeriveKeyArgs, GetAttestationForAppKeyRequest,
15+
GetKeyArgs, GetKeyResponse, GetQuoteResponse, GetTlsKeyArgs, GetTlsKeyResponse, RawQuoteArgs,
16+
SignRequest, SignResponse, TdxQuoteArgs, TdxQuoteResponse, VerifyRequest, VerifyResponse,
17+
WorkerVersion,
1818
};
1919
use dstack_types::{AppKeys, SysConfig};
2020
use ed25519_dalek::ed25519::signature::hazmat::{PrehashSigner, PrehashVerifier};
@@ -179,10 +179,6 @@ impl AppState {
179179
fn attest_response(&self, report_data: [u8; 64]) -> Result<AttestResponse> {
180180
self.inner.platform.attest_response(report_data)
181181
}
182-
183-
fn emit_event(&self, event: &str, payload: &[u8]) -> Result<()> {
184-
self.inner.platform.emit_event(event, payload)
185-
}
186182
}
187183

188184
pub struct InternalRpcHandler {
@@ -328,10 +324,6 @@ impl DstackGuestRpc for InternalRpcHandler {
328324
self.state.quote_response(report_data)
329325
}
330326

331-
async fn emit_event(self, request: EmitEventArgs) -> Result<()> {
332-
self.state.emit_event(&request.event, &request.payload)
333-
}
334-
335327
async fn info(self) -> Result<AppInfo> {
336328
get_info(&self.state, false).await
337329
}
@@ -858,10 +850,6 @@ pNs85uhOZE8z2jr8Pg==
858850
attestation: VersionedAttestation::V1 { attestation }.to_bytes()?,
859851
})
860852
}
861-
862-
fn emit_event(&self, _event: &str, _payload: &[u8]) -> Result<()> {
863-
Ok(())
864-
}
865853
}
866854

867855
let inner = AppStateInner {

sdk/curl/api.md

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -174,34 +174,7 @@ curl --unix-socket /var/run/dstack.sock http://dstack/Info
174174
}
175175
```
176176

177-
### 5. Emit Event
178-
179-
Emit an event to be extended to RTMR3 on TDX platform. This API requires dstack OS 0.5.0 or later.
180-
181-
**Endpoint:** `/EmitEvent`
182-
183-
**Request Parameters:**
184-
185-
| Field | Type | Description | Example |
186-
|-------|------|-------------|----------|
187-
| `event` | string | The event name | `"custom-event"` |
188-
| `payload` | string | Hex-encoded payload data | `"deadbeef"` |
189-
190-
**Example:**
191-
```bash
192-
curl --unix-socket /var/run/dstack.sock -X POST \
193-
http://dstack/EmitEvent \
194-
-H 'Content-Type: application/json' \
195-
-d '{
196-
"event": "custom-event",
197-
"payload": "deadbeef"
198-
}'
199-
```
200-
201-
**Response:**
202-
Empty response with HTTP 200 status code on success.
203-
204-
### 6. Sign (not yet released)
177+
### 5. Sign (not yet released)
205178

206179
Signs a payload.
207180

@@ -238,7 +211,7 @@ curl --unix-socket /var/run/dstack.sock -X POST \
238211
}
239212
```
240213

241-
### 7. Verify (not yet released)
214+
### 6. Verify (not yet released)
242215

243216
Verifies a signature.
244217

@@ -273,7 +246,7 @@ curl --unix-socket /var/run/dstack.sock -X POST \
273246
}
274247
```
275248

276-
### 8. Attest
249+
### 7. Attest
277250

278251
Generates a versioned attestation with the given report data. Returns a dstack-defined attestation format that supports different attestation modes across platforms.
279252
You can submit the returned `attestation` directly to the verifier `/verify` endpoint.

sdk/go/README.md

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -168,37 +168,6 @@ tlsKey2, _ := client.GetTlsKey(ctx, dstack.TlsKeyOptions{})
168168
// tlsKey1.Key != tlsKey2.Key (always different!)
169169
```
170170

171-
### Event Logging
172-
173-
> [!NOTE]
174-
> This feature isn't available in the simulator. We recommend sticking with `report_data` for most cases since it's simpler and safer to use. If you're not super familiar with SGX/TDX attestation quotes, it's best to avoid adding data directly into quotes as it could cause verification issues.
175-
176-
Extend RTMR3 with custom events for audit trails:
177-
178-
```go
179-
// Emit custom events (requires dstack OS 0.5.0+)
180-
eventData := map[string]interface{}{
181-
"action": "transfer",
182-
"amount": 1000,
183-
"timestamp": time.Now().Unix(),
184-
}
185-
eventPayload, _ := json.Marshal(eventData)
186-
187-
err := client.EmitEvent(ctx, "user-action", eventPayload)
188-
if err != nil {
189-
log.Fatal(err)
190-
}
191-
192-
// Events are automatically included in subsequent quotes
193-
quote, err := client.GetQuote(ctx, []byte("audit-data"))
194-
if err != nil {
195-
log.Fatal(err)
196-
}
197-
198-
var events []interface{}
199-
json.Unmarshal([]byte(quote.EventLog), &events)
200-
```
201-
202171
## Optional blockchain helpers (build tags)
203172

204173
By default, the Go SDK builds a **core profile** (attestation, key derivation, info, signing, env encryption).
@@ -655,18 +624,6 @@ cert2, _ := client.GetTlsKey(ctx, dstack.TlsKeyOptions{})
655624
// cert1.Key != cert2.Key (always different)
656625
```
657626

658-
##### `EmitEvent(ctx context.Context, event string, payload []byte) error`
659-
660-
Extends RTMR3 with a custom event for audit logging.
661-
662-
**Parameters:**
663-
- `event`: Event identifier string
664-
- `payload`: Event data
665-
666-
**Requirements:**
667-
- dstack OS version 0.5.0 or later
668-
- Events are permanently recorded in TEE measurements
669-
670627
##### `IsReachable(ctx context.Context) bool`
671628

672629
Tests connectivity to the dstack service.

sdk/go/dstack/client.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -697,21 +697,6 @@ func (c *DstackClient) IsReachable(ctx context.Context) bool {
697697
return err == nil
698698
}
699699

700-
// EmitEvent sends an event to be extended to RTMR3 on TDX platform.
701-
// The event will be extended to RTMR3 with the provided name and payload.
702-
//
703-
// Requires dstack OS 0.5.0 or later.
704-
func (c *DstackClient) EmitEvent(ctx context.Context, event string, payload []byte) error {
705-
if event == "" {
706-
return fmt.Errorf("event name cannot be empty")
707-
}
708-
_, err := c.sendRPCRequest(ctx, "/EmitEvent", map[string]interface{}{
709-
"event": event,
710-
"payload": hex.EncodeToString(payload),
711-
})
712-
return err
713-
}
714-
715700
// Legacy methods for backward compatibility with warnings
716701

717702
// DeriveKey is deprecated. Use GetKey instead.

0 commit comments

Comments
 (0)