Skip to content

Commit c12af85

Browse files
committed
kms: Support for the new mr_image model
1 parent fbf366f commit c12af85

File tree

24 files changed

+445
-106
lines changed

24 files changed

+445
-106
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ members = [
3939
"lspci",
4040
"sdk/rust",
4141
"sodiumbox",
42+
"serde-duration",
4243
]
4344
resolver = "2"
4445

@@ -66,6 +67,7 @@ dstack-types = { path = "dstack-types" }
6667
cert-client = { path = "cert-client" }
6768
lspci = { path = "lspci" }
6869
sodiumbox = { path = "sodiumbox" }
70+
serde-duration = { path = "serde-duration" }
6971

7072
# Core dependencies
7173
anyhow = "1.0.97"

cert-client/src/lib.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@ use ra_tls::{
1010
use tdx_attest::{eventlog::read_event_logs, get_quote};
1111

1212
pub enum CertRequestClient {
13-
Local { ca: CaCert },
14-
Kms { client: KmsClient<RaClient> },
13+
Local {
14+
ca: CaCert,
15+
},
16+
Kms {
17+
client: KmsClient<RaClient>,
18+
vm_config: String,
19+
},
1520
}
1621

1722
impl CertRequestClient {
@@ -27,11 +32,13 @@ impl CertRequestClient {
2732
.context("Failed to sign certificate")?;
2833
Ok(vec![cert.pem(), ca.pem_cert.clone()])
2934
}
30-
CertRequestClient::Kms { client } => {
35+
CertRequestClient::Kms { client, vm_config } => {
3136
let response = client
3237
.sign_cert(SignCertRequest {
38+
api_version: 1,
3339
csr: csr.to_vec(),
3440
signature: signature.to_vec(),
41+
vm_config: vm_config.clone(),
3542
})
3643
.await?;
3744
Ok(response.certificate_chain)
@@ -42,11 +49,15 @@ impl CertRequestClient {
4249
pub async fn get_root_ca(&self) -> Result<String> {
4350
match self {
4451
CertRequestClient::Local { ca } => Ok(ca.pem_cert.clone()),
45-
CertRequestClient::Kms { client } => Ok(client.get_meta().await?.ca_cert),
52+
CertRequestClient::Kms { client, .. } => Ok(client.get_meta().await?.ca_cert),
4653
}
4754
}
4855

49-
pub async fn create(keys: &AppKeys, pccs_url: Option<&str>) -> Result<CertRequestClient> {
56+
pub async fn create(
57+
keys: &AppKeys,
58+
pccs_url: Option<&str>,
59+
vm_config: String,
60+
) -> Result<CertRequestClient> {
5061
match &keys.key_provider {
5162
KeyProvider::Local { key } => {
5263
let ca = CaCert::new(keys.ca_cert.clone(), key.clone())
@@ -74,7 +85,7 @@ impl CertRequestClient {
7485
.into_client()
7586
.context("Failed to create RA client")?;
7687
let client = KmsClient::new(ra_client);
77-
Ok(CertRequestClient::Kms { client })
88+
Ok(CertRequestClient::Kms { client, vm_config })
7889
}
7990
}
8091
}

dstack-types/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,16 @@ pub struct SysConfig {
118118
pub pccs_url: Option<String>,
119119
pub docker_registry: Option<String>,
120120
pub host_api_url: String,
121-
#[serde(with = "hex_bytes", default)]
121+
// JSON serialized VmConfig
122+
pub vm_config: String,
123+
}
124+
125+
#[derive(Deserialize, Serialize, Debug, Clone)]
126+
pub struct VmConfig {
127+
#[serde(with = "hex_bytes")]
122128
pub mr_image: Vec<u8>,
129+
pub cpu_count: u32,
130+
pub memory_size: u64,
123131
}
124132

125133
#[derive(Serialize, Deserialize, Debug, Clone)]

dstack-util/src/system_setup.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55
};
66

77
use anyhow::{anyhow, bail, Context, Result};
8-
use dstack_kms_rpc::GetAppKeyRequest;
8+
use dstack_kms_rpc as rpc;
99
use dstack_types::{
1010
shared_filenames::{
1111
APP_COMPOSE, APP_KEYS, DECRYPTED_ENV, DECRYPTED_ENV_JSON, ENCRYPTED_ENV,
@@ -319,9 +319,16 @@ impl<'a> Stage0<'a> {
319319
.context("Failed to create client")?;
320320
let kms_client = dstack_kms_rpc::kms_client::KmsClient::new(ra_client);
321321
let response = kms_client
322-
.get_app_key(GetAppKeyRequest {})
322+
.get_app_key(rpc::GetAppKeyRequest {
323+
api_version: 1,
324+
vm_config: self.shared.sys_config.vm_config.clone(),
325+
})
323326
.await
324327
.context("Failed to get app key")?;
328+
329+
extend_rtmr3("mr-image", &response.mr_image)
330+
.context("Failed to extend mr-image to RTMR3")?;
331+
325332
let keys = AppKeys {
326333
ca_cert: tmp_ca.ca_cert,
327334
disk_crypt_key: response.disk_crypt_key,
@@ -659,10 +666,13 @@ impl Stage1<'_> {
659666
usage_client_auth: true,
660667
ext_quote: true,
661668
};
662-
let cert_client =
663-
CertRequestClient::create(&self.keys, self.shared.sys_config.pccs_url.as_deref())
664-
.await
665-
.context("Failed to create cert client")?;
669+
let cert_client = CertRequestClient::create(
670+
&self.keys,
671+
self.shared.sys_config.pccs_url.as_deref(),
672+
self.shared.sys_config.vm_config.clone(),
673+
)
674+
.await
675+
.context("Failed to create cert client")?;
666676
let client_key =
667677
KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256).context("Failed to generate key")?;
668678
let client_certs = cert_client

gateway/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ dstack-guest-agent-rpc.workspace = true
4141
http-client = { workspace = true, features = ["prpc"] }
4242
sha2.workspace = true
4343
dstack-types.workspace = true
44+
serde-duration.workspace = true
4445

4546
[target.'cfg(unix)'.dependencies]
4647
nix = { workspace = true, features = ["resource"] }

gateway/src/config.rs

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -107,59 +107,6 @@ pub struct SyncConfig {
107107
pub bootnode: String,
108108
}
109109

110-
mod serde_duration {
111-
use serde::{Deserialize, Deserializer, Serializer};
112-
use std::time::Duration;
113-
114-
pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
115-
where
116-
S: Serializer,
117-
{
118-
if duration == &Duration::MAX {
119-
return serializer.serialize_str("never");
120-
}
121-
let (value, unit) = if duration.as_secs() % (24 * 3600) == 0 {
122-
(duration.as_secs() / (24 * 3600), "d")
123-
} else if duration.as_secs() % 3600 == 0 {
124-
(duration.as_secs() / 3600, "h")
125-
} else if duration.as_secs() % 60 == 0 {
126-
(duration.as_secs() / 60, "m")
127-
} else {
128-
(duration.as_secs(), "s")
129-
};
130-
serializer.serialize_str(&format!("{}{}", value, unit))
131-
}
132-
133-
pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
134-
where
135-
D: Deserializer<'de>,
136-
{
137-
let s = String::deserialize(deserializer)?;
138-
if s.is_empty() {
139-
return Err(serde::de::Error::custom("Duration string cannot be empty"));
140-
}
141-
if s == "never" {
142-
return Ok(Duration::MAX);
143-
}
144-
let (value, unit) = s.split_at(s.len() - 1);
145-
let value = value.parse::<u64>().map_err(serde::de::Error::custom)?;
146-
147-
let seconds = match unit {
148-
"s" => value,
149-
"m" => value * 60,
150-
"h" => value * 3600,
151-
"d" => value * 24 * 3600,
152-
_ => {
153-
return Err(serde::de::Error::custom(
154-
"Invalid time unit. Use s, m, h, or d",
155-
))
156-
}
157-
};
158-
159-
Ok(Duration::from_secs(seconds))
160-
}
161-
}
162-
163110
#[derive(Debug, Clone, Deserialize)]
164111
pub struct Config {
165112
pub wg: WgConfig,

guest-agent/dstack.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ log_level = "debug"
1010
app_name = ""
1111
keys_file = "/dstack/.host-shared/.appkeys.json"
1212
compose_file = "/dstack/.host-shared/app-compose.json"
13+
sys_config_file = "/dstack/.host-shared/.sys-config.json"
1314
public_logs = true
1415
public_sysinfo = true
1516
data_disks = ["/"]

guest-agent/rpc/proto/agent_rpc.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ message WorkerInfo {
199199
string key_provider_info = 12;
200200
// Compose hash
201201
bytes compose_hash = 13;
202+
// VM config
203+
string vm_config = 14;
202204
}
203205

204206
// The response to a WorkerInfo request

guest-agent/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct Config {
2222
pub public_logs: bool,
2323
pub public_sysinfo: bool,
2424
pub compose_file: String,
25+
pub sys_config_file: PathBuf,
2526
#[serde(default)]
2627
pub pccs_url: Option<String>,
2728
pub simulator: Simulator,

0 commit comments

Comments
 (0)