Add event log v2 format with JSON canonical digest#646
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a configurable “v2” runtime event digest format based on RFC 8785 (JCS) canonical JSON, and threads the chosen event-log version plus an RPC opt-in for returning per-event digest preimages (“hash inputs”) through guest-agent, simulator, and callers.
Changes:
- Introduces
EventLogVersion+AppCompose.event_log_version(default v1) and threads it through runtime event emission. - Implements v2 runtime event digest preimage as JCS-canonical JSON and adds optional
hash_inputexposure for relying parties. - Extends guest-agent RPC (
RawQuoteArgs) withinclude_hash_inputsand updates downstream clients/simulator accordingly.
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| ra-tls/src/cert.rs | Adapts to new quote_with_app_id signature by passing a default event log version. |
| kms/src/main_service/upgrade_authority.rs | Updates RawQuoteArgs construction to include include_hash_inputs. |
| guest-agent/src/rpc_service.rs | Threads include_hash_inputs into quote/attest paths and passes event_log_version into event emission. |
| guest-agent/src/backend.rs | Extends backend trait to support include_hash_inputs and versioned runtime event emission. |
| guest-agent/rpc/proto/agent_rpc.proto | Adds include_hash_inputs to RawQuoteArgs and documents behavior. |
| guest-agent-simulator/src/simulator.rs | Adds include_hash_inputs support for simulated quote/attest responses, populating hash inputs when requested. |
| guest-agent-simulator/src/main.rs | Updates simulator backend implementations/tests for new backend trait signatures. |
| guest-agent-simulator/Cargo.toml | Adds dstack-types dependency for EventLogVersion. |
| gateway/src/gen_debug_key.rs | Updates quote request construction for new RawQuoteArgs field. |
| gateway/src/distributed_certbot.rs | Updates quote/attest request construction for new RawQuoteArgs field. |
| dstack-util/src/system_setup.rs | Threads event_log_version from app-compose through multiple RTMR3 emit_runtime_event calls. |
| dstack-util/src/main.rs | Reads event_log_version from host-shared app-compose.json for extend command emission. |
| dstack-types/src/lib.rs | Defines EventLogVersion and adds event_log_version to AppCompose with defaulting. |
| dstack-attest/src/v1.rs | Adds mutable access to TDX event log to populate per-event hash inputs on demand. |
| dstack-attest/src/lib.rs | Updates emit_runtime_event API to accept an explicit event log version. |
| dstack-attest/src/attestation.rs | Adds optional inclusion of per-event hash inputs in event-log JSON and supports event-log version in quote_with_app_id. |
| cc-eventlog/src/tdx.rs | Extends TdxEvent with version + optional hash_input, plus helpers/tests. |
| cc-eventlog/src/tcg.rs | Ensures new TdxEvent fields are initialized for converted TCG events. |
| cc-eventlog/src/runtime_events.rs | Implements v2 canonical JSON digest input, versioned hashing, and extensive tests. |
| cc-eventlog/src/lib.rs | Re-exports EventLogVersion and canonical JSON helper(s). |
| cc-eventlog/Cargo.toml | Adds dstack-types + serde_jcs dependencies. |
| Cargo.lock | Locks new dependencies (serde_jcs, ryu-js, etc.). |
| .gitignore | Ignores .claude/worktrees/. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR introduces an event log v2 digest format based on JCS (RFC 8785) canonical JSON, adds event_log_version to app-compose.json (defaulting to v1 for backward compatibility), and threads the selected version through runtime event emission and attestation/quote surfaces. It also adds an RPC opt-in (include_hash_inputs) to include the exact digest pre-image for runtime events in returned event logs/attestations.
Changes:
- Add
EventLogVersion+AppCompose.event_log_versionand propagate it to allemit_runtime_event(..., version)call sites. - Implement v2 runtime event hashing via canonical JSON and extend event log structures to carry per-event version + optional
hash_input. - Add
include_hash_inputstoRawQuoteArgsand plumb it through guest-agent, simulator, gateway, and kms clients.
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| ra-tls/src/cert.rs | Updates attestation quote call signature to pass an event log version. |
| kms/src/main_service/upgrade_authority.rs | Populates new include_hash_inputs flag in attest RPC call. |
| guest-agent/src/rpc_service.rs | Threads include_hash_inputs through quote/attest RPC handlers; threads event_log_version into event emission; updates tests. |
| guest-agent/src/backend.rs | Extends backend trait to support include_hash_inputs + EventLogVersion; real backend fills optional hash inputs. |
| guest-agent/rpc/proto/agent_rpc.proto | Adds include_hash_inputs to RawQuoteArgs and documents behavior. |
| guest-agent-simulator/src/simulator.rs | Supports include_hash_inputs for simulated quote/attest responses by populating hash_input. |
| guest-agent-simulator/src/main.rs | Updates simulator backend trait implementation and tests for new params. |
| guest-agent-simulator/Cargo.toml | Adds dstack-types dependency for EventLogVersion. |
| gateway/src/gen_debug_key.rs | Updates quote request to include include_hash_inputs. |
| gateway/src/distributed_certbot.rs | Updates quote/attest requests to include include_hash_inputs. |
| dstack-util/src/system_setup.rs | Threads event_log_version through all runtime event emissions during boot/setup. |
| dstack-util/src/main.rs | CLI extend command now reads event_log_version from shared app-compose and uses it for emit_runtime_event. |
| dstack-types/src/lib.rs | Introduces EventLogVersion enum and adds event_log_version field to AppCompose with default. |
| dstack-attest/src/v1.rs | Adds mutable access to TDX event log in platform evidence; updates tests for new fields. |
| dstack-attest/src/lib.rs | Updates emit_runtime_event signature to accept an event log version. |
| dstack-attest/src/attestation.rs | Adds optional hash-input inclusion for event log JSON; adds fill_event_hash_inputs; threads version into quote_with_app_id. |
| cc-eventlog/src/tdx.rs | Extends TdxEvent with version + optional hash_input; implements fill_hash_input; adjusts runtime event conversion. |
| cc-eventlog/src/tcg.rs | Initializes new TdxEvent fields when converting from TCG events. |
| cc-eventlog/src/runtime_events.rs | Adds v2 canonical JSON hash input + EventLogVersion handling for runtime event digests; adds tests. |
| cc-eventlog/src/lib.rs | Re-exports EventLogVersion and v2 helpers/constants. |
| cc-eventlog/Cargo.toml | Adds dependencies for JCS canonicalization (serde_jcs) and shared types. |
| Cargo.lock | Locks new dependencies (serde_jcs, ryu-js, etc.) and updated crate deps. |
| .gitignore | Ignores .claude/worktrees/. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Adds an opt-in v2 runtime event-log digest format (JCS/RFC 8785 canonical JSON) and threads an event_log_version setting from compose config through guest event emission and attestation/quote RPCs, including an include_hash_inputs flag so relying parties can independently verify per-event digests.
Changes:
- Introduce
EventLogVersionandAppCompose.event_log_version(default V1) and plumb it into runtime event emission (RTMR3 extends). - Add
include_hash_inputsto GetQuote/Attest RPCs and populate per-runtime-eventhash_input(hex-encoded digest pre-image) when requested. - Expose event-log version selection in VMM UI + CLI compose generation.
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vmm/ui/src/composables/useVmManager.ts | Add form state + compose serialization for event_log_version (omit when V1). |
| vmm/ui/src/components/CreateVmDialog.ts | Add UI dropdown to select V1 vs V2 event log format. |
| vmm/src/vmm-cli.py | Add --event-log-version and write it into app-compose.json. |
| ra-tls/src/cert.rs | Update RA-TLS quote callsite for new quote_with_app_id signature. |
| kms/src/main_service/upgrade_authority.rs | Update attest request to include include_hash_inputs flag. |
| guest-agent/src/rpc_service.rs | Thread include_hash_inputs into quote/attest; pass event_log_version into emit_event. |
| guest-agent/src/backend.rs | Extend backend trait to support include_hash_inputs + event-log versioned emission. |
| guest-agent/rpc/proto/agent_rpc.proto | Add include_hash_inputs field + clarified semantics in comments. |
| guest-agent-simulator/src/simulator.rs | Support include_hash_inputs in simulated quote/attest responses. |
| guest-agent-simulator/src/main.rs | Update simulator backend trait implementation + tests for new signatures. |
| guest-agent-simulator/Cargo.toml | Add dstack-types dependency for EventLogVersion. |
| gateway/src/gen_debug_key.rs | Populate include_hash_inputs in quote requests. |
| gateway/src/distributed_certbot.rs | Populate include_hash_inputs in quote/attest requests. |
| dstack-util/src/system_setup.rs | Pass event_log_version into all runtime event emissions during boot setup. |
| dstack-util/src/main.rs | Make extend command pick event-log version from shared app-compose.json. |
| dstack-types/src/lib.rs | Introduce EventLogVersion and add event_log_version to AppCompose. |
| dstack-attest/src/v1.rs | Expose mutable access to TDX event log for filling hash_input in simulator/tests. |
| dstack-attest/src/lib.rs | Version-aware emit_runtime_event API. |
| dstack-attest/src/attestation.rs | Add include_hash_inputs plumbing for JSON event log; version-aware wire encoding selection. |
| cc-eventlog/src/tdx.rs | Add version + optional hash_input to TdxEvent; compute digest input on demand. |
| cc-eventlog/src/tcg.rs | Initialize new TdxEvent fields when converting from TCG events. |
| cc-eventlog/src/runtime_events.rs | Add v2 canonical JSON digest input + EventLogVersion in RuntimeEvent. |
| cc-eventlog/src/lib.rs | Re-export EventLogVersion and v2 helpers/constants. |
| cc-eventlog/Cargo.toml | Add deps for JCS + version type. |
| Cargo.lock | Lockfile updates for new crates. |
| .gitignore | Ignore .claude/worktrees/. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new runtime event-log digest format (v2) based on RFC 8785 JCS canonical JSON, plumbs an event_log_version setting from compose/UI/CLI into runtime event emission, and extends attestation/quote APIs to optionally expose per-event digest pre-images and a merged binary CCEL event log.
Changes:
- Add
event_log_version(default v1) to app compose handling (UI + CLI + guest/system setup) and thread it into RTMR3 runtime event emission. - Implement v2 runtime-event hashing (JCS canonical JSON pre-image) and optional
hash_inputinclusion for relying-party verification. - Add
event_log_ccelto quote responses and update SDKs to decode it.
Reviewed changes
Copilot reviewed 28 out of 30 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vmm/ui/src/composables/useVmManager.ts | Adds event_log_version to form state and compose generation logic. |
| vmm/ui/src/components/CreateVmDialog.ts | Adds UI dropdown to select event log format (V1/V2). |
| vmm/src/vmm-cli.py | Adds --event-log-version flag and writes it into app-compose.json. |
| sdk/rust/types/src/dstack.rs | Adds event_log_ccel to GetQuoteResponse plus decoding helper. |
| sdk/python/src/dstack_sdk/dstack_client.py | Adds event_log_ccel to response model plus decoder. |
| sdk/js/src/index.ts | Extends GetQuoteResponse interface with event_log_ccel. |
| sdk/go/dstack/client.go | Extends GetQuoteResponse with EventLogCCEL + decoder. |
| ra-tls/src/cert.rs | Updates quote_with_app_id call site for new signature. |
| kms/src/main_service/upgrade_authority.rs | Supplies include_hash_inputs: false in attest call. |
| guest-agent/src/rpc_service.rs | Threads include_hash_inputs through quote/attest; passes event_log_version to emit_event. |
| guest-agent/src/backend.rs | Adds include_hash_inputs support and returns merged event_log_ccel. |
| guest-agent/rpc/proto/agent_rpc.proto | Adds include_hash_inputs request field and event_log_ccel in response, with updated docs. |
| guest-agent-simulator/src/simulator.rs | Simulator support for include_hash_inputs and new event_log_ccel field. |
| guest-agent-simulator/src/main.rs | Updates simulator backend trait impl/tests for new signatures. |
| guest-agent-simulator/Cargo.toml | Adds dstack-types dependency for EventLogVersion. |
| gateway/src/gen_debug_key.rs | Updates get_quote call to include include_hash_inputs: false. |
| gateway/src/distributed_certbot.rs | Updates quote/attest calls to include include_hash_inputs: false. |
| dstack-util/src/system_setup.rs | Emits runtime events using event_log_version from compose. |
| dstack-util/src/main.rs | Extender command now reads compose to choose event-log version. |
| dstack-types/src/lib.rs | Introduces EventLogVersion enum and adds it to AppCompose. |
| dstack-attest/src/v1.rs | Adds helpers for mutating TDX event log in tests/serialization paths. |
| dstack-attest/src/lib.rs | Updates emit_runtime_event to accept event-log version. |
| dstack-attest/src/attestation.rs | Adds include_hash_inputs support and versioned wire-format upgrade logic; adds CCEL builder plumbing. |
| cc-eventlog/src/tdx.rs | Adds per-event version + optional hash_input, and helpers to populate it. |
| cc-eventlog/src/tcg.rs | Adds CCEL helpers and encoder for runtime events as TCG_PCR_EVENT2 records. |
| cc-eventlog/src/runtime_events.rs | Implements v1/v2 digest pre-images, v2 canonical JSON, and adds version to runtime events. |
| cc-eventlog/src/lib.rs | Re-exports EventLogVersion, exposes tcg module, and adds CCEL roundtrip test. |
| cc-eventlog/Cargo.toml | Adds serde_jcs + dstack-types + or-panic dependencies. |
| Cargo.lock | Locks new Rust dependencies (serde_jcs, ryu-js, etc.). |
| .gitignore | Ignores .claude/worktrees/. |
Comments suppressed due to low confidence (1)
cc-eventlog/src/tdx.rs:116
TdxEvent::digest()always recomputes the digest for runtime events fromevent_payload. After this PR, runtime events encoded into the merged CCEL log useevent_payloadas the digest pre-image bytes (not the original payload/name tuple), andTryFrom<TcgEvent>currently defaultsversionto V1. That combination makesdigest()return a value that can disagree with the storeddigestfield for runtime events parsed from the merged CCEL, which can break replay/verification when using the decodedTdxEventAPI.
Consider changing digest() to prefer returning the stored self.digest when it is present (non-empty), and only recompute when self.digest is empty (e.g., for synthesized/stripped events).
pub fn digest(&self) -> Vec<u8> {
if let Some(runtime_event) = self.to_runtime_event() {
return runtime_event.sha384_digest().to_vec();
}
self.digest.clone()
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot resolve the merge conflicts in this pull request |
Resolved. The two conflicts were:
|
d3fd44d to
b953c66
Compare
Summary
event_log_versionfield toapp-compose.json(default 1, backward compatible)event_type0x08000001; version is carried out-of-band viaRuntimeEvent::version(scale/serde), not inside the hashed contentSHA384({"name":"<event-name>","payload":"<hex>","type":134217729})(keys are JCS-sorted:name<payload<type)preimage(hex-encoded) by default for independent verification; V1 event output remains unchangedGetQuotereturns the merged binary CCEL event log by default (fail-open to an empty field if CCEL export is unavailable)vmm-cli.py compose --event-log-versionand a dropdown in the VMM Web UIThis enables relying parties (e.g., Intel ITA) to define fine-grained trust policies on individual event claims (e.g.,
input.event.name == "compose-hash") instead of matching the full RTMR3 value, which varies across VM instances due to other measured events.Enabling v2 for an app
Via vmm-cli
Omitting
--event-log-versionkeeps the field out ofapp-compose.json, so existing compose hashes for v1 apps are unchanged.Via VMM Web UI
"Create VM" dialog → "Event log format" dropdown (under Networking). Defaults to V1; pick V2 to opt in.
Consuming v2 attestation
Once the CVM is booted, call
GetQuote/Attest; V2 events include their canonical JSON pre-image by default:Each V2 runtime event in the returned
event_logcarries apreimagefield whose value is a hex-encoded string. Clients verify digests independently with:Wire format notes
event_type.to_le_bytes() || ":" || event_name || ":" || payload(little-endian is now pinned; previouslyto_ne_bytes(), identical on x86){"name":"<event-name>","payload":"<hex>","type":134217729}. Field names are generic (no keyword collisions in Rego / CEL) and match common messaging/event-protocol conventions (CloudEvents, MQTT, JWT).sha384(hex_decode(preimage)) == event.digest; V1 output stays unchangedWire-format compatibility safety-net
Attestation::into_versioned()conditionally upgrades to V1 msgpack when any runtime event reports a non-V1 version (SCALE V0 skips theversionfield for legacy binary compat, which would otherwise drop v2 information on the wire). V1-only attestations keep the V0/SCALE encoding, so existing consumers are unaffected.from_bytesdetects the encoding by leading byte, so the receiver side needs no changes.Test plan
cargo check --all-featurespassescargo clippypasses (with-D warnings -D clippy::expect_used -D clippy::unwrap_used)cargo fmt --check --allpassescargo test -p cc-eventlog— 25 tests including v1 backward compat, v2 digest, canonical JSON escaping/sorting/idempotency, mixed v1/v2 replay, scale round-tripcargo test -p dstack-attest— 8 tests including msgpack round-trip with new fields and V0/V1 dispatch coveragevmm-cli.py compose --event-log-version 2writes the field; omitting the flag keeps existing compose hashes stableevent_log_version: 2; boot completes (done), KMS verifier replays RTMR3 without mismatch, and guest-reported digests match the new canonical JSON bytewise