Close the #796 auth gaps in docs and tooling#801
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aligns dstack’s operator-facing docs and tooling with the post-#796 “auth guards the full management surface” reality, making installs and clients authenticate correctly by default and warning operators when the VMM is exposed without auth.
Changes:
- Secure-by-default
dstackup install: generates/reuses a VMM management API bearer token, renders[auth] enabled = true, persistsclient_token_path, and threads the token through internal VMM calls (incl. destroy). - Tooling support for auth-enabled VMMs:
dstack-cliandvmm-cli.pynow sendAuthorization: Bearer <token>(andvmm-cli.pyfails fast on half-configured Basic auth). - Docs + test config hygiene: deployment/security/gateway/KMS docs document the auth surfaces; test configs are annotated as “TEST ONLY”.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| dstack/vmm/src/vmm-cli.py | Add bearer token support; reject incomplete Basic creds; wire --token/DSTACK_VMM_TOKEN. |
| dstack/vmm/src/main.rs | Warn when binding the management API publicly with [auth] enabled = false. |
| dstack/test-scripts/snp-e2e-smoke.sh | Annotate weak test-only KMS admin credential. |
| dstack/kms/README.md | Document KMS admin authentication configuration (token hash). |
| dstack/http-client/src/prpc.rs | Add bearer token support for pRPC client requests. |
| dstack/http-client/src/lib.rs | Add request helper that can attach extra headers. |
| dstack/gateway/test-run/test_suite.sh | Annotate test-only insecure_no_auth. |
| dstack/gateway/test-run/e2e/configs/gateway-{1,2,3}.toml | Annotate test-only hardcoded admin token + debug RPC enablement. |
| dstack/crates/dstackup/src/state.rs | Persist client_token_path in install state. |
| dstack/crates/dstackup/src/install.rs | Generate/reuse token, write it to disk, enable [auth], and pass token into VMM connectivity checks. |
| dstack/crates/dstackup/src/destroy.rs | Use recorded token file to authenticate VMM calls during teardown. |
| dstack/crates/dstack-cli/src/main.rs | Wire --token/env/token-file fallback into VMM connects and /logs. |
| dstack/crates/dstack-cli-core/src/vmm.rs | Add connect_with_token and send bearer auth for both pRPC and /logs. |
| dstack/crates/dstack-cli-core/src/config.rs | Render [auth] enabled/tokens into generated vmm.toml + add unit tests. |
| docs/vmm-cli-user-guide.md | Update auth guidance to reflect full-surface auth + new token support. |
| docs/deployment.md | Add required [auth] block and explain surface-wide VMM auth and KMS admin auth distinction. |
| docs/dstack-gateway.md | Document gateway admin API authentication configuration. |
| docs/security/security-best-practices.md | Add management/admin API auth best practices section. |
| docs/tutorials/* | Fix tutorial snippets that previously sent no auth due to password-only Basic env. |
| CHANGELOG.md | Add unreleased entry documenting the #796 auth surface. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
kvinwang
force-pushed
the
worktree-fix-auth-config-gaps
branch
from
July 20, 2026 12:43
00f36bd to
76c294a
Compare
kvinwang
force-pushed
the
worktree-fix-auth-config-gaps
branch
from
July 20, 2026 13:35
a615c9c to
06b7599
Compare
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
#796 added a shared
dstack-api-authcrate that fail-closes and protects the full external surface of VMM ([auth]), Gateway admin ([core.admin]), and KMS admin (admin_token_hash). The code landed correctly, but the docs and tools never caught up, so several official paths still produce or describe an unauthenticated deployment:docs/deployment.mdbindsaddress = "tcp:0.0.0.0:9080"with no[auth]section at all — post-feat(auth): protect VMM with shared API authentication #796 that exposes the entire VMM control API (create/stop CVM, UI, pRPC) to the network with no credential. The doc's "Auth Server Options" only covers the KMS boot webhook, which reads as if auth were handled.dstackupships auth off. The generatedvmm.tomlhardcoded[auth] enabled = false / tokens = [], so the automated installer's default contradicts the hand-written tutorial path (which generates a token and enables auth).dstack-vmmsilently allowedenabled = falseon a non-loopback bind — no log, no localhost check (Gateway warns on its equivalentinsecure_no_auth).dstack-cli's--tokenflag was accepted then discarded (let _ = &cli.token;), so it could not talk to an auth-enabled remote VMM.vmm-cli.pysupported only Basic and required both user and password — setting onlyDSTACK_VMM_AUTH_PASSWORD(as several tutorials did) silently sent no auth header, so requests went out unauthenticated and failed confusingly.htpasswd_file/ gateway & KMS admin auth undocumented. The new htpasswd support and the KMSadmin_token_hashappear nowhere in any user-facing deploy/tutorial/security doc;docs/dstack-gateway.mdnever mentions[core.admin].admin_token = "e2e-admin-token",insecure_no_auth = true, andadmin_token_hash = "00"carried no "do not use in production" marker.Fix
Tools now authenticate, the installer is secure-by-default, the server warns, and every operator-facing doc explains the auth added by #796.
dstackup installmints a 256-bit token (/dev/urandom, written0600to<config>/vmm-auth-token), renders[auth] enabled = truewith it, recordsclient_token_pathin the install state, and threads the token through every internal VMM connect (preflight, reachability, KMS deploy,destroy). Re-runs reuse the existing token so credentials stay stable.dstack-cliwires--tokenfor real (precedence:--token→DSTACK_VMM_TOKEN→ the installed token file), sendingAuthorization: Bearerover both the pRPC client and the/logsroute.http-clientgained header support + a prpc bearer token.vmm-cli.pyadds--token/DSTACK_VMM_TOKEN(Bearer), and now errors on a half-set Basic credential instead of silently sending nothing.dstack-vmmlogs awarn!when the management API binds a non-loopback TCP address while[auth] enabled = false.deployment.mdgains a real[auth]block + prose; new "Admin API authentication" sections indocs/dstack-gateway.md,dstack/kms/README.md, anddocs/security/security-best-practices.md; the password-only tutorial snippets are fixed (addDSTACK_VMM_AUTH_USER=admin/ switch toDSTACK_VMM_TOKEN);vmm-cli-user-guide.mddocuments the token form and drops the stale "guards only /logs" framing;CHANGELOG.mdrecords feat(auth): protect VMM with shared API authentication #796.TEST ONLY - do not use in productionannotations.Verification
cargo build+cargo testfordstackup,dstack-cli-core,dstack-cli,dstack-vmm,http-client— all pass;cargo clippyclean;cargo fmtapplied.vmm.tomlrendersenabled = true+tokens = ["…"]when a token is set and a valid empty-token list otherwise.vmm-cli.py:python -m py_compilepasses; verifiedVmmClientraises on user-only and password-only credentials, and constructs cleanly for token-only and full-Basic.ensure_adminprotectsclear_image_cacheonly (onboarding is attestation-gated), so the deployment.md admin-auth note is scoped to admin RPCs, not onboarding.End-to-end verification on a TDX host
Ran a real
dstack-vmmagainst dstackup-generated artifacts in an isolated prefix (non-default ports,--no-startso no systemd units and no interference with the host's existing install), then exercised the full auth round-trip and cleaned up.Generated artifacts:
vmm-auth-tokenwritten-rw-------(0600), 64 hex chars.vmm.tomlrendered[auth] enabled = truewithtokens = ["<same token>"].Round-trip against a live VMM on
127.0.0.1:19080(auth fairing active):Authorization: BearerX-Admin-Tokenheaderdstack --tokendstack, no tokendstackviaDSTACK_VMM_TOKENvmm-cli.py --tokenvmm-cli.py, password onlyvmm-cli.py, user onlyvmm-cli.py, Basicadmin:tokendstack --prefix(auto-reads token from install state, no--token/--host)The full installer chain (
dstackup install→ running VMM → KMS-in-CVM) still needs a systemd-level install and is not covered here.