`bootstrap_keys()` auto-bootstrap path does not write `bootstrap-info.json`
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 45/100
調査の方向性
onboard_service.rs の bootstrap_keys() から始め、手動の bootstrap() パスと比較します。次に、config.rs の bootstrap_info() と main_service.rs の GetMeta を調べます。TDX 対応のセットアップで自動ブートストラップのフローを検証し、quote_enabled の動作も確認します。また、GetMeta が後続の kms:set-info 登録向けに設定済みの bootstrap 情報を公開していることを確認します。
索引モデルが issue の本文から書いたものです。
説明
When KMS is configured with auto_bootstrap_domain (non-empty string in kms.toml), the auto-bootstrap code path in onboard_service.rs:bootstrap_keys() generates keys and stores them via keys.store(cfg), but never writes bootstrap-info.json.
This causes GetMeta to return bootstrap_info: null, which blocks the kms:set-info hardhat task from registering the KMS on-chain.
Steps to Reproduce
-
Deploy KMS CVM with
auto_bootstrap_domainset inkms.toml:[onboard] auto_bootstrap_domain = "kms.example.com" quote_enabled = true -
KMS starts, auto-bootstrap runs successfully (keys generated, certs created)
-
Query GetMeta:
curl -sk https://localhost:9100/prpc/KMS.GetMeta?json | jq .bootstrap_info -
Result:
null
Root Cause
Auto-bootstrap (onboard_service.rs:330-339):
pub(crate) async fn bootstrap_keys(cfg: &KmsConfig) -> Result<()> {
let keys = Keys::generate(
&cfg.onboard.auto_bootstrap_domain,
cfg.onboard.quote_enabled,
)
.await
.context("Failed to generate keys")?;
keys.store(cfg)?; // Stores 8 files (keys, certs, rpc-domain) — NOT bootstrap-info.json
Ok(())
}
Manual bootstrap (onboard_service.rs:54-78):
async fn bootstrap(self, request: BootstrapRequest) -> Result<BootstrapResponse> {
let quote_enabled = self.state.config.onboard.quote_enabled;
let keys = Keys::generate(&request.domain, quote_enabled)
.await
.context("Failed to generate keys")?;
let k256_pubkey = keys.k256_key.verifying_key().to_sec1_bytes().to_vec();
let ca_pubkey = keys.ca_key.public_key_der();
let attestation = if quote_enabled {
Some(attest_keys(&ca_pubkey, &k256_pubkey).await?)
} else {
None
};
let cfg = &self.state.config;
let response = BootstrapResponse {
ca_pubkey,
k256_pubkey,
attestation: attestation.unwrap_or_default(),
};
// Store the bootstrap info
safe_write(cfg.bootstrap_info(), serde_json::to_vec(&response)?)?; // ← Writes the file
keys.store(cfg)?;
Ok(response)
}
The manual path extracts public keys, optionally generates an attestation quote via attest_keys(), constructs a BootstrapResponse, and writes it to {cert_dir}/bootstrap-info.json (defined in config.rs:88-90 as self.cert_dir.join("bootstrap-info.json")). The auto-bootstrap path does none of this.
GetMeta (main_service.rs:323-326) silently returns None when the file is missing:
let bootstrap_info = fs::read_to_string(self.state.config.bootstrap_info())
.ok()
.and_then(|s| serde_json::from_str(&s).ok());
Impact
GetMetareturnsbootstrap_info: nullkms:set-infohardhat task fails (cannot read/parse null bootstrap info)- KMS public keys and TDX attestation quote are never registered on-chain
- Applications cannot verify KMS attestation through the smart contract
- The entire on-chain trust anchor is missing
No workaround exists — bootstrap-info.json is only written in one place in the codebase (the manual bootstrap() RPC handler at line 75). No other service or background task populates it.
History
ae75c86e(2025-01-12): Addedbootstrap_keys()— nobootstrap-info.jsonwrite6900f54e(2025-01-15): Addedbootstrap-info.jsonwrite to the manualbootstrap()path only
The auto path has never written this file since it was introduced.
Suggested Fix
Add public key extraction, attestation quote generation, and bootstrap-info.json writing to bootstrap_keys(), mirroring the manual bootstrap() path:
pub(crate) async fn bootstrap_keys(cfg: &KmsConfig) -> Result<()> {
let keys = Keys::generate(
&cfg.onboard.auto_bootstrap_domain,
cfg.onboard.quote_enabled,
)
.await
.context("Failed to generate keys")?;
keys.store(cfg)?;
// Write bootstrap-info.json (same as manual bootstrap path)
let k256_pubkey = keys.k256_key.verifying_key().to_sec1_bytes().to_vec();
let ca_pubkey = keys.ca_key.public_key_der();
let attestation = if cfg.onboard.quote_enabled {
Some(attest_keys(&ca_pubkey, &k256_pubkey).await?)
} else {
None
};
let response = BootstrapResponse {
ca_pubkey,
k256_pubkey,
attestation: attestation.unwrap_or_default(),
};
safe_write(cfg.bootstrap_info(), serde_json::to_vec(&response)?)?;
Ok(())
}
Note: The attest_keys() function (line 351) generates a TDX attestation quote binding both the P256 CA public key and the secp256k1 key. This is needed for on-chain registration to include a valid attestation.
Also affected: feat/auto-onboard-kms branch
The auto_onboard_keys() function on the unmerged feat/auto-onboard-kms feature branch has the same gap — it generates keys and stores them but does not write bootstrap-info.json.
Environment
- dstack version: v0.5.7
- Platform: TDX-enabled server (Intel Xeon with TDX support)
- Ubuntu 24.04 LTS
- 主要言語
- Rust
- スター
- 551
- フォーク
- 97
- 平均マージ
- 19時間 22分
- マージ済み PR(30日)
- 109
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
Dstack-TEE/dstack のほかの issue
-
難易度 5/5 1週間以上 初心者へのやさしさ 30/100
Dstack-TEE/dstack#1301 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
Dstack-TEE/dstack#1300 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
Dstack-TEE/dstack#1299 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
Dstack-TEE/dstack#1298 ·
-
P0
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
Dstack-TEE/dstack#1297 ·
Dstack-TEE/dstack の issue をすべて見る
似ている issue
-
bug github_actions
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
registrystack/registry-stack#1393 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
longbridge/gpui-kit#3223 ·
-
bug engine
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
rocky-data/rocky#2181 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
oasisprotocol/oasis-sdk#2523 ·
-
[indexer] [QA] Add a focused test for the new NonRetryableError / assertSocketAlive() behavior. オープンbot:ai-assisted component:indexer QA-roadmap status:untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
midnightntwrk/midnight-indexer#1557 ·