Skip to content

Commit 068a618

Browse files
committed
guest-agent: Request demo cert lazily
1 parent c0c670e commit 068a618

File tree

6 files changed

+70
-30
lines changed

6 files changed

+70
-30
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,6 @@ serde_yaml2 = "0.1.2"
218218

219219
luks2 = "0.5.0"
220220
scopeguard = "1.2.0"
221+
222+
[profile.release]
223+
panic = "abort"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[Unit]
2+
Wants=dstack-guest-agent.service
3+
After=dstack-guest-agent.service
4+
5+
[Service]
6+
TimeoutStartSec=0
7+
ExecStartPre=/bin/sh -c 'while ! systemctl is-active --quiet dstack-guest-agent.service || [ ! -S /var/run/dstack.sock ] || [ ! -S /var/run/tappd.sock ]; do sleep 1; done'

cert-client/src/lib.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,13 @@ impl CertRequestClient {
6868
.context("Failed to create CA")?;
6969
Ok(CertRequestClient::Local { ca })
7070
}
71-
KeyProvider::Kms { url, .. } => {
72-
let tmp_client =
73-
RaClient::new(url.into(), true).context("Failed to create RA client")?;
74-
let tmp_client = KmsClient::new(tmp_client);
75-
let tmp_ca = tmp_client
76-
.get_temp_ca_cert()
77-
.await
78-
.context("Failed to get temp CA cert")?;
79-
let client_cert = generate_ra_cert(tmp_ca.temp_ca_cert, tmp_ca.temp_ca_key)
71+
KeyProvider::Kms {
72+
url,
73+
tmp_ca_key,
74+
tmp_ca_cert,
75+
..
76+
} => {
77+
let client_cert = generate_ra_cert(tmp_ca_cert.clone(), tmp_ca_key.clone())
8078
.context("Failed to generate RA cert")?;
8179
let ra_client = RaClientConfig::builder()
8280
.remote_uri(url.clone())

dstack-types/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ pub enum KeyProvider {
192192
url: String,
193193
#[serde(with = "hex_bytes")]
194194
pubkey: Vec<u8>,
195+
tmp_ca_key: String,
196+
tmp_ca_cert: String,
195197
},
196198
}
197199

dstack-util/src/system_setup.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ impl<'a> Stage0<'a> {
561561
.await
562562
.context("Failed to get temp ca cert")?
563563
};
564-
let cert_pair = generate_ra_cert(tmp_ca.temp_ca_cert, tmp_ca.temp_ca_key)?;
564+
let cert_pair = generate_ra_cert(tmp_ca.temp_ca_cert.clone(), tmp_ca.temp_ca_key.clone())?;
565565
let ra_client = RaClientConfig::builder()
566566
.tls_no_check(false)
567567
.tls_built_in_root_certs(false)
@@ -619,6 +619,8 @@ impl<'a> Stage0<'a> {
619619
key_provider: KeyProvider::Kms {
620620
url: kms_url,
621621
pubkey: root_pubkey,
622+
tmp_ca_key: tmp_ca.temp_ca_key,
623+
tmp_ca_cert: tmp_ca.temp_ca_cert,
622624
},
623625
};
624626
Ok(keys)

guest-agent/src/rpc_service.rs

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// SPDX-License-Identifier: Apache-2.0
44

5-
use std::sync::Arc;
5+
use std::sync::{Arc, RwLock};
66

77
use anyhow::{Context, Result};
88
use cert_client::CertRequestClient;
@@ -28,6 +28,7 @@ use ring::rand::{SecureRandom, SystemRandom};
2828
use serde_json::json;
2929
use sha3::{Digest, Keccak256};
3030
use tdx_attest::eventlog::read_event_logs;
31+
use tracing::error;
3132

3233
use crate::config::Config;
3334

@@ -41,23 +42,14 @@ struct AppStateInner {
4142
keys: AppKeys,
4243
vm_config: String,
4344
cert_client: CertRequestClient,
44-
demo_cert: String,
45+
demo_cert: RwLock<String>,
4546
}
4647

47-
impl AppState {
48-
pub async fn new(config: Config) -> Result<Self> {
49-
let keys: AppKeys = serde_json::from_str(&fs::read_to_string(&config.keys_file)?)
50-
.context("Failed to parse app keys")?;
51-
let sys_config: SysConfig =
52-
serde_json::from_str(&fs::read_to_string(&config.sys_config_file)?)
53-
.context("Failed to parse VM config")?;
54-
let vm_config = sys_config.vm_config;
55-
let cert_client =
56-
CertRequestClient::create(&keys, config.pccs_url.as_deref(), vm_config.clone())
57-
.await
58-
.context("Failed to create cert signer")?;
48+
impl AppStateInner {
49+
async fn request_demo_cert(&self) -> Result<String> {
5950
let key = KeyPair::generate().context("Failed to generate demo key")?;
60-
let demo_cert = cert_client
51+
let demo_cert = self
52+
.cert_client
6153
.request_cert(
6254
&key,
6355
CertConfig {
@@ -68,20 +60,55 @@ impl AppState {
6860
usage_client_auth: true,
6961
ext_quote: true,
7062
},
71-
config.simulator.enabled,
63+
self.config.simulator.enabled,
7264
)
7365
.await
7466
.context("Failed to get app cert")?
7567
.join("\n");
76-
Ok(Self {
68+
Ok(demo_cert)
69+
}
70+
}
71+
72+
impl AppState {
73+
fn maybe_request_demo_cert(&self) {
74+
let state = self.inner.clone();
75+
if !state.demo_cert.read().unwrap().is_empty() {
76+
return;
77+
}
78+
tokio::spawn(async move {
79+
match state.request_demo_cert().await {
80+
Ok(demo_cert) => {
81+
*state.demo_cert.write().unwrap() = demo_cert;
82+
}
83+
Err(e) => {
84+
error!("Failed to request demo cert: {e}");
85+
}
86+
}
87+
});
88+
}
89+
90+
pub async fn new(config: Config) -> Result<Self> {
91+
let keys: AppKeys = serde_json::from_str(&fs::read_to_string(&config.keys_file)?)
92+
.context("Failed to parse app keys")?;
93+
let sys_config: SysConfig =
94+
serde_json::from_str(&fs::read_to_string(&config.sys_config_file)?)
95+
.context("Failed to parse VM config")?;
96+
let vm_config = sys_config.vm_config;
97+
let cert_client =
98+
CertRequestClient::create(&keys, config.pccs_url.as_deref(), vm_config.clone())
99+
.await
100+
.context("Failed to create cert signer")?;
101+
let me = Self {
77102
inner: Arc::new(AppStateInner {
78103
config,
79104
keys,
80105
cert_client,
81-
demo_cert,
106+
demo_cert: RwLock::new(String::new()),
82107
vm_config,
83108
}),
84-
})
109+
};
110+
me.maybe_request_demo_cert();
111+
Ok(me)
85112
}
86113

87114
pub fn config(&self) -> &Config {
@@ -136,6 +163,7 @@ pub async fn get_info(state: &AppState, external: bool) -> Result<AppInfo> {
136163
} else {
137164
state.inner.vm_config.clone()
138165
};
166+
state.maybe_request_demo_cert();
139167
Ok(AppInfo {
140168
app_name: state.config().app_compose.name.clone(),
141169
app_id: app_info.app_id,
@@ -145,7 +173,7 @@ pub async fn get_info(state: &AppState, external: bool) -> Result<AppInfo> {
145173
os_image_hash: app_info.os_image_hash.clone(),
146174
key_provider_info: String::from_utf8(app_info.key_provider_info).unwrap_or_default(),
147175
compose_hash: app_info.compose_hash.clone(),
148-
app_cert: state.inner.demo_cert.clone(),
176+
app_cert: state.inner.demo_cert.read().unwrap().clone(),
149177
tcb_info,
150178
vm_config,
151179
})

0 commit comments

Comments
 (0)