Skip to content

Commit 627f19a

Browse files
authored
Merge pull request #585 from Dstack-TEE/docs/update-kms-test-guides
fix: unify RA-TLS cert format and fix onboard os_image_hash
2 parents 5342e3e + abfebc0 commit 627f19a

File tree

4 files changed

+25
-30
lines changed

4 files changed

+25
-30
lines changed

kms/src/main_service/upgrade_authority.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,19 @@ pub(crate) async fn ensure_kms_allowed(
224224
cfg: &KmsConfig,
225225
attestation: &VerifiedAttestation,
226226
) -> Result<()> {
227-
let boot_info = build_boot_info(attestation, false, "")
227+
let mut boot_info = build_boot_info(attestation, false, "")
228228
.context("failed to build KMS boot info from attestation")?;
229+
// Workaround: old source KMS instances use the legacy cert format (separate TDX_QUOTE +
230+
// EVENT_LOG OIDs) which lacks vm_config, resulting in an empty os_image_hash.
231+
// Fill it from the local KMS's own value. This is safe because mrAggregated already
232+
// validates OS image integrity transitively through the RTMR measurement chain.
233+
// TODO: remove once all source KMS instances use the unified PHALA_RATLS_ATTESTATION format.
234+
if boot_info.os_image_hash.is_empty() {
235+
let local_info = local_kms_boot_info(cfg.pccs_url.as_deref())
236+
.await
237+
.context("failed to get local KMS boot info for os_image_hash fallback")?;
238+
boot_info.os_image_hash = local_info.os_image_hash;
239+
}
229240
let response = cfg
230241
.auth_api
231242
.is_app_allowed(&boot_info, true)

ra-tls/src/cert.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@ use x509_parser::x509::SubjectPublicKeyInfo;
2525

2626
use crate::oids::{
2727
PHALA_RATLS_APP_ID, PHALA_RATLS_APP_INFO, PHALA_RATLS_ATTESTATION, PHALA_RATLS_CERT_USAGE,
28-
PHALA_RATLS_EVENT_LOG, PHALA_RATLS_TDX_QUOTE,
2928
};
3029
use crate::traits::CertExt;
3130
#[cfg(feature = "quote")]
3231
use dstack_attest::attestation::QuoteContentType;
33-
use dstack_attest::attestation::{AppInfo, Attestation, AttestationQuote, VersionedAttestation};
32+
use dstack_attest::attestation::{AppInfo, Attestation, VersionedAttestation};
3433

3534
/// A CA certificate and private key.
3635
pub struct CaCert {
@@ -389,21 +388,8 @@ impl<Key> CertRequest<'_, Key> {
389388
add_ext(&mut params, PHALA_RATLS_CERT_USAGE, usage);
390389
}
391390
if let Some(ver_att) = self.attestation {
392-
let VersionedAttestation::V0 { attestation } = &ver_att;
393-
match &attestation.quote {
394-
AttestationQuote::DstackTdx(tdx_quote) => {
395-
// For backward compatibility, we serialize the quote to the classic oids.
396-
let event_log = serde_json::to_vec(&tdx_quote.event_log)
397-
.context("Failed to serialize event log")?;
398-
add_ext(&mut params, PHALA_RATLS_TDX_QUOTE, &tdx_quote.quote);
399-
add_ext(&mut params, PHALA_RATLS_EVENT_LOG, &event_log);
400-
}
401-
_ => {
402-
// The event logs are too large on GCP TDX to put in the certificate, so we strip them
403-
let attestation_bytes = ver_att.clone().into_stripped().to_scale();
404-
add_ext(&mut params, PHALA_RATLS_ATTESTATION, &attestation_bytes);
405-
}
406-
}
391+
let attestation_bytes = ver_att.clone().into_stripped().to_scale();
392+
add_ext(&mut params, PHALA_RATLS_ATTESTATION, &attestation_bytes);
407393
}
408394
if let Some(ca_level) = self.ca_level {
409395
params.is_ca = IsCa::Ca(BasicConstraints::Constrained(ca_level));
@@ -576,7 +562,7 @@ pub fn generate_ra_cert_with_app_id(
576562
#[cfg(test)]
577563
mod tests {
578564
use super::*;
579-
use dstack_attest::attestation::TdxQuote;
565+
use dstack_attest::attestation::{AttestationQuote, TdxQuote};
580566
use rcgen::PKCS_ECDSA_P256_SHA256;
581567
use scale::Encode;
582568

tests/docs/kms-bootstrap-onboard.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Operational notes:
7878
4. On teepod with gateway, onboard mode usually uses the `-8000` URL, while runtime TLS KMS RPC usually uses the `-8000s` URL. **Port forwarding** (`--port tcp:0.0.0.0:<host-port>:8000`) is simpler than gateway for testing, because gateway requires the auth API to return a `gatewayAppId` at boot time.
7979
5. If you use a very small custom webhook instead of the real auth service, `KMS.GetMeta` may fail because `auth_api.get_info()` expects extra chain / contract metadata fields. In that case, use `GetTempCaCert` as the runtime readiness probe.
8080
6. dstack CVMs use QEMU user-mode networking — the host is reachable at **`10.0.2.2`** from inside the CVM. The `source_url` in `Onboard.Onboard` must use a CVM-reachable address (e.g., `https://10.0.2.2:<port>/prpc`), not `127.0.0.1`.
81-
7. **Remote KMS attestation has an empty `osImageHash`.** When the receiver verifies the source KMS during onboard, the `osImageHash` is empty because `vm_config` is unavailable for remote attestation. Auth configs for receiver-side checks must include `"0x"` in the `osImages` array.
81+
7. **~~Remote KMS attestation has an empty `osImageHash`.~~** Fixed: RA-TLS certs now use the unified `PHALA_RATLS_ATTESTATION` format which preserves `vm_config`. For old source KMS instances, the receiver-side check fills `osImageHash` from the local KMS's own value automatically. No special `"0x"` entry in `osImages` is needed anymore.
8282

8383
---
8484

@@ -109,7 +109,7 @@ At minimum, both policies must allow the KMS instance they serve. During onboard
109109

110110
For `auth-simple`, `kms.mrAggregated = []` is a deny-all policy for KMS. Add the current KMS MR values explicitly when switching a test from deny to allow.
111111

112-
Include `"0x"` in the `osImages` array for configs used in receiver-side onboard checks (see operational note 7 above).
112+
You no longer need `"0x"` in the `osImages` array — the receiver-side check now resolves `osImageHash` automatically.
113113

114114
### 4.3 Deploy `kms-src` and `kms-dst`
115115

tests/docs/kms-self-authorization.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ This guide is written as a deployment-and-test runbook so an AI agent can follow
2525
> 7. KMS now always requires quote/attestation. For local development without TDX hardware, use `sdk/simulator` instead of trying to run a no-attestation KMS flow.
2626
> 8. For `auth-simple`, `kms.mrAggregated = []` is a deny-all policy for KMS. Use that as the baseline deny configuration, then add the measured KMS MR values for allow cases.
2727
> 9. **Port forwarding is simpler than gateway for testing.** Using `--gateway` requires the auth API to return a valid `gatewayAppId`, which adds unnecessary complexity. Use `--port tcp:0.0.0.0:<host-port>:8000` instead.
28-
> 10. **Remote KMS attestation has an empty `osImageHash`.** When the receiver verifies the source KMS during onboard, the `osImageHash` field in the attestation is empty (because `vm_config` is not available for the remote attestation). Auth configs for receiver-side checks must include `"0x"` in the `osImages` array to match this empty hash.
28+
> 10. **~~Remote KMS attestation has an empty `osImageHash`.~~** Fixed: RA-TLS certs now use the unified `PHALA_RATLS_ATTESTATION` format which preserves `vm_config`. For old source KMS instances that still use the legacy cert format, the receiver-side `ensure_kms_allowed` automatically fills `osImageHash` from the local KMS's own value. No special `"0x"` entry in `osImages` is needed anymore.
2929
> 11. The `source_url` in the `Onboard.Onboard` request must use an address **reachable from inside the CVM** (e.g., `https://10.0.2.2:<port>/prpc`), not `127.0.0.1` which is the CVM's own loopback.
3030
3131
---
@@ -49,13 +49,13 @@ This guide is written as a deployment-and-test runbook so an AI agent can follow
4949

5050
## 1. Why this document exists
5151

52-
PR #538 already proposes a richer `kms/e2e/` framework, but as of **2026-03-19** it is still open/draft and touches overlapping KMS files. To avoid waiting for that PR, this guide uses:
52+
This guide provides a standalone test procedure that does not depend on a dedicated e2e framework. It uses:
5353

5454
- existing KMS deploy flows
5555
- `auth-simple` as a controllable auth API
5656
- manual RPC calls via `curl`
5757

58-
This keeps the test independent from PR #538 while still exercising real deployment paths.
58+
This exercises real deployment paths with minimal dependencies.
5959

6060
---
6161

@@ -98,7 +98,7 @@ Policy responsibilities:
9898

9999
Before starting, make sure the following are available:
100100

101-
1. A branch or image containing the PR #573 KMS changes
101+
1. A KMS image built from current `master` (includes PR #573 auth checks, #579 mandatory attestation, #581 dedup refactor)
102102
2. A working `dstack-vmm` or teepod deployment target
103103
3. Two routable KMS onboard URLs
104104
4. `bun` installed on the host, because `kms/auth-simple` runs on Bun
@@ -315,12 +315,10 @@ All three values above are expected to be hex strings **without** the `0x` prefi
315315

316316
Use a wrong `mrAggregated` value while allowing the observed OS image.
317317

318-
> **Important:** include `"0x"` in `osImages` to handle remote KMS attestation during onboard receiver-side checks, where `osImageHash` is empty because `vm_config` is unavailable for the remote attestation.
319-
320318
```bash
321319
cat > /tmp/kms-self-auth/deny-by-mr.json <<'EOF'
322320
{
323-
"osImages": ["0xREPLACE_OS", "0x"],
321+
"osImages": ["0xREPLACE_OS"],
324322
"gatewayAppId": "any",
325323
"kms": {
326324
"mrAggregated": ["0x0000000000000000000000000000000000000000000000000000000000000000"],
@@ -337,7 +335,7 @@ EOF
337335
```bash
338336
cat > /tmp/kms-self-auth/allow-single.json <<'EOF'
339337
{
340-
"osImages": ["0xREPLACE_OS", "0x"],
338+
"osImages": ["0xREPLACE_OS"],
341339
"gatewayAppId": "any",
342340
"kms": {
343341
"mrAggregated": ["0xREPLACE_MR"],
@@ -354,7 +352,7 @@ EOF
354352
```bash
355353
cat > /tmp/kms-self-auth/allow-src-and-dst.json <<'EOF'
356354
{
357-
"osImages": ["0xREPLACE_SRC_OS", "0xREPLACE_DST_OS", "0x"],
355+
"osImages": ["0xREPLACE_SRC_OS", "0xREPLACE_DST_OS"],
358356
"gatewayAppId": "any",
359357
"kms": {
360358
"mrAggregated": ["0xREPLACE_SRC_MR", "0xREPLACE_DST_MR"],

0 commit comments

Comments
 (0)