A config-based auth server for dstack KMS webhook authorization. Validates boot requests against a JSON configuration file.
| Auth Server | Use Case |
|---|---|
| auth-simple | Production deployments with config-file-based whitelisting |
| auth-eth | Production deployments with on-chain governance |
| auth-mock | Development and testing only |
bun installCreate auth-config.json (see auth-config.example.json).
For KMS deployment, you must allowlist the OS image hash and at least one KMS
identity value via kms.mrAggregated (the early/boot-mr-done aggregate MR,
same pinning model as bare TDX). App compose hashes still use
apps.<appId>.composeHashes.
{
"osImages": ["0x0b327bcd642788b0517de3ff46d31ebd3847b6c64ea40bacde268bb9f1c8ec83"],
"kms": {
"mrAggregated": ["0x<kms-early-mr-aggregated>"],
"allowAnyDevice": true
},
"apps": {}
}Add more fields as you deploy Gateway and apps:
{
"osImages": ["0x..."],
"allowedTcbStatuses": ["UpToDate"],
"allowedAdvisoryIds": [],
"gatewayAppId": "0x...",
"kms": {
"mrAggregated": ["0x..."],
"devices": [],
"allowAnyDevice": true
},
"apps": {
"0xYourAppId": {
"composeHashes": ["0xabc...", "0xdef..."],
"devices": [],
"allowAnyDevice": true
}
}
}AWS NitroTPM has no TDX/SNP-style TCB advisory surface, so the KMS normalizes a
verified NitroTPM attestation to tcbStatus: "UpToDate" before calling
auth-simple. Pin KMS via early mrAggregated (boot-mr-done snapshot), same as
bare TDX. Prefer a stable AMI/os_image_hash and empty TPM key-provider id so
that early MR is precomputable.
{
"osImages": ["0x<aws-os-image-hash>"],
"allowedAdvisoryIds": [],
"kms": {
"mrAggregated": ["0x<kms-early-mr-aggregated>"],
"devices": [],
"allowAnyDevice": true
},
"apps": {
"0x<app-id>": {
"composeHashes": ["0x<app-compose-hash>"],
"devices": [],
"allowAnyDevice": true
}
}
}The verifier that calls auth-simple must already have verified the NitroTPM
Attestation Document, AWS NitroTPM PKI chain, boot PCRs, PCR14 launch-event
replay, and OS image binding. PCR8 is an optional third-party shortcut, not a
required dstack check; see docs/aws-ec2-production-verifier-runbook.md.
auth-simple authorizes the resulting canonical BootInfo; it does not verify
raw NitroTPM evidence by itself.
| Field | Required | Description |
|---|---|---|
osImages |
Yes | Allowed OS image hashes (from digest.txt) |
gatewayAppId |
No | Gateway app ID (add after Gateway deployment) |
allowedTcbStatuses |
No | Allowed verifier-derived TCB status strings. Defaults to ["UpToDate"]; non-up-to-date SNP/TDX statuses remain fail-closed unless explicitly allowlisted for testing. |
allowedAdvisoryIds |
No | Advisory IDs permitted in advisoryIds. Defaults to [], which rejects any advisory. |
kms.mrAggregated |
Yes | Allowed KMS early aggregate MR values (boot-mr-done). |
kms.devices |
No | Allowed KMS device IDs |
kms.allowAnyDevice |
No | If true, skip device ID check for KMS |
apps.<appId>.composeHashes |
No | Allowed compose hashes for this app |
apps.<appId>.devices |
No | Allowed device IDs for this app |
apps.<appId>.allowAnyDevice |
No | If true, skip device ID check for this app |
For experimental AMD SEV-SNP dry-run authorization, keep the default fail-closed TCB policy unless you intentionally want the auth webhook to accept non-up-to-date verifier-derived SNP BootInfo. To exercise the dry-run path without enabling key release, allowlist the recomputed SNP mrAggregated, osImageHash, app/compose identity, device/chip identity, and any non-default allowedTcbStatuses/allowedAdvisoryIds values explicitly. KMS still rejects SNP before returning app keys, KMS keys, or app certificates.
OS Image Hash:
# From meta-dstack build output
cat images/digest.txtCompose Hash:
sha256sum .app-compose.json | awk '{print "0x"$1}'# Run with hot reload
bun run dev# Run directly
bun run start
# Or build first
bun run build| Variable | Default | Description |
|---|---|---|
PORT |
3000 | Server port |
AUTH_CONFIG_PATH |
./auth-config.json | Path to config file |
Health check and server info.
Response:
{
"status": "ok",
"configPath": "./auth-config.json",
"gatewayAppId": "0x..."
}App boot authorization.
Request:
{
"teeVariant": "dstack-tdx",
"mrAggregated": "0x...",
"osImageHash": "0x...",
"appId": "0x...",
"composeHash": "0x...",
"instanceId": "0x...",
"deviceId": "0x...",
"tcbStatus": "UpToDate",
"advisoryIds": []
}Response:
{
"isAllowed": true,
"reason": "",
"gatewayAppId": "0x..."
}KMS boot authorization.
Request: Same as /bootAuth/app
Response: Same as /bootAuth/app
tcbStatusmust be listed inallowedTcbStatuses(default: only"UpToDate"). AWS NitroTPM is normalized to"UpToDate"by the KMS before it reaches auth-simple.- Every
advisoryIdsentry must be listed inallowedAdvisoryIds(default: none allowed) osImageHashmust be inosImagesarraymrAggregatedmust be in thekms.mrAggregatedearly/boot-mr-done allowlistdeviceIdmust be inkms.devicesunlessallowAnyDeviceis true
tcbStatusmust be listed inallowedTcbStatuses(default: only"UpToDate"). AWS NitroTPM is normalized to"UpToDate"by the KMS before it reaches auth-simple.- Every
advisoryIdsentry must be listed inallowedAdvisoryIds(default: none allowed) osImageHashmust be inosImagesarrayappIdmust exist inappsobjectcomposeHashmust be in app'scomposeHashesarraydeviceIdmust be in app'sdevices(unlessallowAnyDeviceis true)
The config file is re-read on every request. No restart required after config changes.
Configure KMS to use webhook auth pointing to this server:
[core.auth_api]
type = "webhook"
[core.auth_api.webhook]
url = "http://localhost:3000"# Run tests
bun run test
# Run once
bun run test:run- auth-eth - On-chain governance auth server
- auth-mock - Development/testing auth server (always allows)
- Deployment Guide - Full deployment instructions