From b88697d4ad4211cba25a68ed552e4500577ad52e Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 13 Nov 2026 18:28:41 -0800 Subject: [PATCH] docs: mark dstack-auth as development, testing and evaluation only dstack-auth takes its policy from a file on the host, so whoever controls the host can authorize any compose hash and obtain app keys, and nobody else can audit what was authorized. That does not meet the trust model production deployments rely on; point production users at auth-eth or an equivalent service instead. Signed-off-by: Kevin Wang --- docs/aws-attested-instance-security-evaluation.md | 2 +- docs/aws-ec2-production-verifier-runbook.md | 9 +++++---- docs/deployment.md | 2 +- docs/dstack-auth-operations.md | 5 +++++ docs/onboarding.md | 2 +- dstack/crates/dstack-auth/src/main.rs | 4 +++- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/aws-attested-instance-security-evaluation.md b/docs/aws-attested-instance-security-evaluation.md index 1b118f56d..42703390b 100644 --- a/docs/aws-attested-instance-security-evaluation.md +++ b/docs/aws-attested-instance-security-evaluation.md @@ -38,7 +38,7 @@ NitroTPM path meets them today. | P4 | Runtime application identity is cryptographically bound | RTMR3 `compose-hash`, `app-id`, `instance-id`, `key-provider`; event log replay | SHA384 `PCR14` event-log replay is the authoritative binding (RTMR3 analogue; non-resettable). Launch events: `system-preparing`, `app-id`, `compose-hash`, zero or more ordered `init-script-hash` events, `instance-id`, `boot-mr-done`, `key-provider`, `storage-fs`, `storage-encrypted`, `system-ready` (`dstack/dstack-util/src/system_setup.rs`). GPU launches also include `gpu-policy-hash` before `instance-id`, and `gpu-attestation` after `boot-mr-done` and before `key-provider`. `dstack-attest`, `dstack-verifier`, and KMS reject missing/mismatched PCR14 and bad replay. Optionally, the guest extends the raw `MrConfig` V2 `config_id` into `PCR8` once (`PCR8 = sha384(0^48 || config_id)`) so a lightweight third-party verifier can check compose hash + key provider without event-log replay; dstack's own verifier and KMS do not check PCR8. | | P5 | Challenge/liveness and caller key binding | `report_data` challenge or RA-TLS public key hash in quote | RA-TLS binds `report_data` to the TLS certificate public key. KMS key release is bound to the live RA-TLS handshake; external `/verify` callers supply and check their own `report_data` challenge. The low-level NitroTPM document verifier also rejects stale or far-future document timestamps. | | P6 | Secret release only to attested code | dstack KMS verifies attestation, checks auth policy, derives per-app keys | dstack KMS verifies the NitroTPM attestation, runs the same `verify_os_image_hash_for_aws_nitro_tpm` binding check as the verifier, builds `BootInfo` from verified boot PCRs plus PCR14 launch events, and checks auth policy before deriving app keys (`dstack/kms/src/main_service.rs`). AWS NitroTPM key release is gated behind the opt-in `aws_nitro_tpm_key_release` flag (default false in `kms.toml`). | -| P7 | Key-release policy is not controlled by the untrusted account admin | KMS runs inside TEE; policy from auth API/contracts; KMS identity measured | Satisfied with dstack KMS or another verifiable secret authority outside the untrusted AWS account admin's control. A NitroTPM-backed dstack KMS keeps root material out of account-admin snapshots and clones. The policy backend (dstack-auth in a trusted control plane, or on-chain `DstackKms`/`DstackApp`) must be outside the workload account admin's control. Same-account AWS KMS fails this property if the admin can change key policy, create grants, or call secret-bearing operations through a policy they control. | +| P7 | Key-release policy is not controlled by the untrusted account admin | KMS runs inside TEE; policy from auth API/contracts; KMS identity measured | Satisfied with dstack KMS or another verifiable secret authority outside the untrusted AWS account admin's control. A NitroTPM-backed dstack KMS keeps root material out of account-admin snapshots and clones. The policy backend (on-chain `DstackKms`/`DstackApp` or an equivalent service; dstack-auth is for development, testing and evaluation only) must be outside the workload account admin's control. Same-account AWS KMS fails this property if the admin can change key policy, create grants, or call secret-bearing operations through a policy they control. | | P8 | Operator cannot inject boot-time or runtime inputs that affect secrets without detection | Host-shared files are measured or independently authenticated; KMS URLs not trusted, KMS key identity measured | App TPM access is enforced by measurement, not by a container sandbox: `init_script`, `pre_launch_script`, and the docker-compose are measured into the app-compose hash, hence into the governed app identity, and replayed into non-resettable `PCR14`, so an operator cannot alter app inputs without changing the measured identity and being denied key release. Production dstack-os AWS images exclude SSH, cloud-init, SSM, EC2 Instance Connect, and serial login (checked by `audit-aws-ec2-image-hardening.sh`). IMDS/operator-provided config must not be a secret-affecting input unless measured or authenticated. | | P9 | Persistent state confidentiality from account admin | dstack disk key derived after attestation; encrypted env vars decrypted only inside CVM | The local TPM key provider seals the disk seed under a SHA384 PCR policy over `[4, 7, 8, 12, 14]` (`AWS_NITRO_PCRS` in `dstack/tpm-attest/src/lib.rs`), so the sealed seed survives same-instance stop/start but does not transfer with cloned EBS volumes to another instance. EBS snapshots and volumes remain account-admin visible at the AWS control plane, so persisted confidential state must stay encrypted inside the instance and AMIs must contain no secrets. | | P10 | Network and TLS endpoint identity is attestation-bound | RA-TLS / Zero Trust HTTPS / gateway attestation; TLS keys generated in TEE | The Rust RA-TLS verifier exposes `verify_der`/`verify_pem`, which extract the certificate's embedded attestation, verify it with the platform verifier (including AWS NitroTPM), and require `report_data = QuoteContentType::RaTlsCert(SubjectPublicKeyInfo)`. `dstack-verifier --verify-cert` provides an operator/relying-party certificate evidence path that also binds `os_image_hash`. AWS attestation alone does not protect DNS, load balancers, or admin-controlled proxies; clients must require this RA-TLS check, signed responses, or an attested gateway. | diff --git a/docs/aws-ec2-production-verifier-runbook.md b/docs/aws-ec2-production-verifier-runbook.md index ff68cb4ba..de64f1481 100644 --- a/docs/aws-ec2-production-verifier-runbook.md +++ b/docs/aws-ec2-production-verifier-runbook.md @@ -18,8 +18,9 @@ and endpoint identity. - The dstack monorepo sources pinned at the exact release revision, for the reproducible rebuild. - A dstack verifier built from this repository. -- The production auth policy backend: `dstack-auth`, auth-eth contracts, or an - equivalent verifier-controlled service. +- The production auth policy backend: auth-eth contracts or an equivalent + verifier-controlled service. `dstack-auth` is for development, testing and + evaluation only. - For public services, the endpoint's RA-TLS certificate. ## 1. Verify Release Evidence @@ -209,8 +210,8 @@ For AWS NitroTPM, the policy must require: `instance-id`, `key-provider`); - a `report_data` challenge for external verifier flows that need liveness. -With `dstack-auth`, the TCB status and advisories are checked only when the -allowlist sets them, so set both explicitly: +When evaluating with `dstack-auth`, note that the TCB status and advisories are +checked only when the allowlist sets them, so set both explicitly: ```json { diff --git a/docs/deployment.md b/docs/deployment.md index 9095496dd..57758f79b 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -126,7 +126,7 @@ Production KMS requires: | Server | Use Case | Configuration | |--------|----------|---------------| -| [dstack-auth](./dstack-auth-operations.md) | Config-file-based whitelisting | JSON config file | +| [dstack-auth](./dstack-auth-operations.md) | Config-file-based whitelisting for development, testing and evaluation only | JSON config file | | [auth-eth](../dstack/kms/auth-eth/) | On-chain governance via the `DstackKms`/`DstackApp` contracts in the same directory | Ethereum RPC + contract | | Custom | Your own authorization logic | Implement webhook interface | diff --git a/docs/dstack-auth-operations.md b/docs/dstack-auth-operations.md index 54b203580..fe3d98471 100644 --- a/docs/dstack-auth-operations.md +++ b/docs/dstack-auth-operations.md @@ -2,6 +2,11 @@ > **This guide is for self-hosted deployments** on your own TDX hardware. For cloud deployments, see [Quickstart](./quickstart.md). +> [!WARNING] +> `dstack-auth` is intended for development, testing and evaluation only. Do not +> use it to protect production keys; use [auth-eth](../dstack/kms/auth-eth/) or +> an equivalent production-grade authorization service instead. + `dstack-auth` is the file-based KMS authorization webhook. It allowlists OS images, KMS instances and apps in one JSON file. For on-chain governance, use [auth-eth](../dstack/kms/auth-eth/) instead diff --git a/docs/onboarding.md b/docs/onboarding.md index 2aa0dc588..9ff9ea1b3 100644 --- a/docs/onboarding.md +++ b/docs/onboarding.md @@ -33,7 +33,7 @@ For multi-node production, Gateway TLS, custom domains, or on-chain governance, - Source and build cache under `/var/cache/dstack`. - Runtime sockets and process state under `/run/dstack`. - A localhost-only VMM dashboard on port `9080`. -- A local `dstack-auth` webhook and `dstack-vmm` systemd unit. +- A local `dstack-auth` webhook (development, testing and evaluation only) and `dstack-vmm` systemd unit. - A single KMS CVM unless you pass `--no-kms`. - A direct host port mapping for your app. diff --git a/dstack/crates/dstack-auth/src/main.rs b/dstack/crates/dstack-auth/src/main.rs index 06efdb8bb..f19e0a11c 100644 --- a/dstack/crates/dstack-auth/src/main.rs +++ b/dstack/crates/dstack-auth/src/main.rs @@ -4,6 +4,8 @@ //! `dstack-auth` — the file-based KMS auth webhook. //! +//! Intended for development, testing and evaluation only; not for production. +//! //! Runs on the host as `dstack-auth.service`; the KMS-in-CVM reaches it at //! `http://10.0.2.2:` under user-mode networking and POSTs `BootInfo` to //! `/authorizeApp` (compose-hash allowlist) and `/authorizeKms` (mrAggregated @@ -40,7 +42,7 @@ use std::path::PathBuf; #[command( name = "dstack-auth", version, - about = "single-operator KMS auth webhook" + about = "single-operator KMS auth webhook (development, testing and evaluation only)" )] struct Cli { /// path to the allowlist JSON (re-read on every request).