guest-agent: add the versioned v1 API - #1114
Closed
kvinwang wants to merge 7 commits into
Closed
Conversation
| /// legacy `info` is the caller's `path` verbatim -- so a caller that passed the | ||
| /// v1 `info` byte string as a v0 path would reproduce a v1 key. Different salts | ||
| /// close that by construction, whatever either side puts in `info`. | ||
| pub(crate) const KDF_SALT: &[u8] = b"dstack-guest-v1"; |
Collaborator
Author
|
Reopening against next as a single combined PR (freeze + v1 + fixes + SDK). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1113. Implements the versioned guest-agent API for 0.6.0.
Problem
The unversioned guest-agent API accreted design debt it cannot shed without breaking 0.5.x clients:
GetTlsKeynames a key what is really certificate issuance;GetKey'spurposeandalgorithmare accepted but do not domain-separate the derived key (the same 32 bytes serve both curves);Sign/Verifyare pure computation that grant no capabilityGetKeydoes not already grant;Inforeturns a triple-nested JSON blob duplicating half its own top-level fields; and the signature-chain claimkeccak256("{purpose}:{hex(pubkey)}")lets a caller-chosenpurposeproduce nearly arbitrary signed strings.Fix
A versioned API selected by URL path only. Every surface is a frozen v0 fossil plus a v1:
/(alias),/v0/v1: IssueCert, GetKey, Attest, AttestGpu, Info, Version/prpc(alias),/prpc/v0(Info, Version, GetAttestationForAppKey)/prpc/v1: Info, Version, AttestAppKey, Healthv1 keeps only what needs the TEE: derivation, attestation, and cert issuance relayed to KMS
SignCert.IssueCert— honest name for whatGetTlsKeydid: issue a certificate, generating a fresh key as the integrated one-step mode.GetKey(domain, algorithm)— new KDF with real domain separation:HKDF-SHA256(salt="dstack-guest-v1", IKM=app_root_k256, info=LP("dstack-guest-v1-key")||LP(algorithm)||LP(domain)), length-prefixed encoding, per-algorithm keys, v1-specific salt so no v0 input can reproduce a v1 key. Chain claim binds(algorithm, domain, raw pubkey)under a length-prefixed tag — structurally unforgeable from the v0 claim format (a v0 preimage's tail is lowercase hex; the v1 length prefix contains 0x00).Attest(sole CVM attestation entry;GetQuotestays v0-only),AttestGpu, and a flatInfo(identity + configuration; MRTD/RTMRs/event log deliberately excluded — they are attestation data and belong toAttest, quote-backed).Sign/Verify/EmitEvent/GpuInfoin v1. Never-released post-0.5.11 additions are removed from the unversioned surfaces, which now diff clean against v0.5.11./prpc/v1/Health.Normative spec:
docs/guest-api-v1.md— byte-level KDF and claim encodings, verification steps, migration contract (SDKs will ship ClientV0/ClientV1; v1 keys deliberately differ from v0 keys for the same input).Verification
v0.5.11(comments stripped): servicesDstackGuest,Worker,Tappdidentical; 16/19 messages byte-identical, 3 differ byreservedonly.a_v0_path_cannot_reproduce_a_v1_keyfeeds the v1 info byte string to the legacy KDF as a path and asserts divergence; forgery test asserts the structural hex/0x00 property, not just inequality./v0return byte-identical bodies on both listeners; each mount serves only its own surface.