Repository navigation
Conversation
kvinwang
force-pushed
the
feat/launch-ticket-contracts
branch
5 times, most recently
from
November 14, 2026 11:46
c44e920 to
d1d9149
Compare
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
… key imports Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
kvinwang
force-pushed
the
feat/launch-ticket-contracts
branch
from
November 14, 2026 16:36
289171b to
5d6078f
Compare
Signed-off-by: Kevin Wang <wy721@qq.com>
This branch has not been deployed
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.
Problem
The
LAUNCH_TOKENpattern runs in the guest: the app-layer variant checks the token after the KMS has already released keys, andrequirements.launch_token_hashrelies on the guest OS enforcing it before key provisioning. Either way the guest OS must be bug-free, and rotating the token means changing the compose hash.Fix
Gate key release on a launch ticket that the contract checks before the KMS hands out anything.
AuthorizationRequestgainslaunchTicketHash(breaking; 0.6.4 contracts are not deployed yet).DstackAppaddssetRequireLaunchTicket,addLaunchTicket(hash, label),removeLaunchTicketandlaunchTickets(), checked first forapp_get_key/app_get_certat every app epoch; a missing or unknown ticket is rejected as "Invalid launch ticket". Labels are only logged in the added event.DstackKmsadds the same for KMS instances, checked only forkms_import_keys, the one operation that hands a joining KMS the root keys. A required ticket refuses the legacyisAppAllowed/isKmsAllowed, so old KMS binaries and auth backends fail closed.sha256("dstack-launch-ticket/v1:" || ticket), for apps and KMS instances alike. Orthogonal torequirements.launch_token_hash. The KMS and VMM refuse tickets outside 32..1024 bytes or with surrounding whitespace.GET /reportsrootCaPubkey, the CA key of the current root epoch.launch_ticketfield of sys-config, not ofvm_config, which attestations embed. The guest sends it inGetAppKeyandSignCert; a joining KMS takes it inOnboardand sends it inGetKmsKey.RaClientruns its cert validator only on the response, so the ticket andsource_tokenwould reach any TEE answering at the source URL. ra-rpc can now pin issuer keys in the rustls verifier (non-CA leaf, given special usage, valid, signed by a pinned key; https only, no redirects), and onboarding pins akms:rpcleaf of the current root CA from its own auth API: nothing is sent to a source without the registered roots.VmInfo.launch_ticket_hash).vmm-cli launch-ticket new|hash,deploy --launch-ticket-file,update --launch-ticket-file|--no-launch-ticket,dstack-util get-keys --launch-ticket-file, and a field in the web UI.DstackKmsis 24,113 bytes after this (EIP-170 limit 24,576).A guest sends its ticket before it has authenticated the KMS, so the ticket's secrecy also rests on the CVM-to-KMS network path; a non-bearer scheme could close that in a follow-up.
Compatibility
Tickets need the VMM, the KMS and the auth backend at 0.6.4 or later, and a guest OS at 0.6.4 or later or a 0.5.x release with the launch ticket backport (#1579). Upgrade every KMS instance before
setRequireKmsLaunchTicket(true): older ones authorize serving throughisKmsAllowed, which then refuses. Onboarding needs the auth backend'sGET /to reportrootCaPubkeyand anhttps://source URL, so upgrade the auth backend before the KMS.Testing
forge test --ffi(116), halmos on the four symbolic suites (39 checks), auth-ethbun run check,cargo testfor dstack-kms, dstack-auth, ra-rpc (including a TLS test that a server failing the pin, by issuer, usage, CA flag or expiry, receives no request bytes), dstack-vmm, cert-client, dstack-types and dstack-util, vmm-cli unittest and the VMM UI tests.End to end on TDX hardware, with a guest image, VMM, KMS and contracts built from this branch (KMS in CVMs, contracts on anvil behind auth-eth):
Invalid launch ticket; an allowed ticket boots and gets a KMS-signed certificate. The ticket appears in noVmInfo, guest-agentInfo,vm_configor certificate DER.http://source is refused, and a KMS with unregistered roots fails the handshake and receives no request.v0.6.4before this PR, or 0.5.14), with the rest from this branch: old 0.6.4 and 0.5.14 guests, an old VMM, and an old KMS all boot when no ticket is required and are denied when one is; a 0.5.x guest with backport(v0.5.x): present the launch ticket to the KMS #1579 boots with a ticket. An old joining KMS onboards from a new source only when no KMS ticket is required, and so does a new joiner from an old source. An old auth-eth with the new contract, and a new auth-eth with the old contract, fail closed; an old auth-eth ignoreslaunchTicketHash; onboarding against an old auth-eth fails for want ofrootCaPubkey.