Skip to content

Commit 0154940

Browse files
committed
kms: Use intermediate cert to sign app certs
1 parent fdba5f4 commit 0154940

File tree

4 files changed

+47
-9
lines changed

4 files changed

+47
-9
lines changed

cert-client/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl CertRequestClient {
2323
match self {
2424
CertRequestClient::Local { ca } => {
2525
let cert = ca
26-
.sign_csr(csr, None)
26+
.sign_csr(csr, None, "app:custom")
2727
.context("Failed to sign certificate")?;
2828
Ok(vec![cert.pem(), ca.pem_cert.clone()])
2929
}

kms/src/main_service.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use kms_rpc::{
1111
use ra_rpc::{Attestation, CallContext, RpcCall};
1212
use ra_tls::{
1313
attestation::VerifiedAttestation,
14-
cert::{CaCert, CertSigningRequest},
14+
cert::{CaCert, CertRequest, CertSigningRequest},
1515
kdf,
1616
};
1717
use scale::Decode;
@@ -138,6 +138,26 @@ impl RpcHandler {
138138
tproxy_app_id: response.tproxy_app_id,
139139
})
140140
}
141+
142+
fn derive_app_ca(&self, app_id: &[u8]) -> Result<CaCert> {
143+
let context_data = vec![app_id, b"app-ca"];
144+
let app_key = kdf::derive_ecdsa_key_pair(&self.state.root_ca.key, &context_data)
145+
.context("Failed to derive app disk key")?;
146+
let req = CertRequest::builder()
147+
.key(&app_key)
148+
.org_name("Dstack")
149+
.subject("Dstack App CA")
150+
.ca_level(0)
151+
.app_id(app_id)
152+
.special_usage("app:ca")
153+
.build();
154+
let app_ca = self
155+
.state
156+
.root_ca
157+
.sign(req)
158+
.context("Failed to sign App CA")?;
159+
Ok(CaCert::from_parts(app_key, app_ca))
160+
}
141161
}
142162

143163
impl KmsRpc for RpcHandler {
@@ -245,13 +265,16 @@ impl KmsRpc for RpcHandler {
245265
let app_info = self
246266
.ensure_app_attestation_allowed(&attestation, false, true)
247267
.await?;
248-
let cert = self
249-
.state
250-
.root_ca
251-
.sign_csr(&csr, Some(&app_info.boot_info.app_id))
268+
let app_ca = self.derive_app_ca(&app_info.boot_info.app_id)?;
269+
let cert = app_ca
270+
.sign_csr(&csr, Some(&app_info.boot_info.app_id), "app:custom")
252271
.context("Failed to sign certificate")?;
253272
Ok(SignCertResponse {
254-
certificate_chain: vec![cert.pem(), self.state.root_ca.pem_cert.clone()],
273+
certificate_chain: vec![
274+
cert.pem(),
275+
app_ca.pem_cert.clone(),
276+
self.state.root_ca.pem_cert.clone(),
277+
],
255278
})
256279
}
257280
}

kms/src/onboard_service.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl Keys {
126126
let ca_cert = CertRequest::builder()
127127
.org_name("Dstack")
128128
.subject("Dstack KMS CA")
129-
.ca_level(0)
129+
.ca_level(1)
130130
.key(&ca_key)
131131
.build()
132132
.self_signed()?;

ra-tls/src/cert.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ impl CaCert {
5353
})
5454
}
5555

56+
/// Instantiate a new CA certificate with a given private key and pem cert.
57+
pub fn from_parts(key: KeyPair, cert: Certificate) -> Self {
58+
Self {
59+
pem_cert: cert.pem(),
60+
cert,
61+
key,
62+
}
63+
}
64+
5665
/// Load a CA certificate and private key from files.
5766
pub fn load(cert_path: impl AsRef<Path>, key_path: impl AsRef<Path>) -> Result<Self> {
5867
let pem_key = fs::read_to_string(key_path).context("Failed to read key file")?;
@@ -66,7 +75,12 @@ impl CaCert {
6675
}
6776

6877
/// Sign a remote certificate signing request.
69-
pub fn sign_csr(&self, csr: &CertSigningRequest, app_id: Option<&[u8]>) -> Result<Certificate> {
78+
pub fn sign_csr(
79+
&self,
80+
csr: &CertSigningRequest,
81+
app_id: Option<&[u8]>,
82+
usage: &str,
83+
) -> Result<Certificate> {
7084
let pki = rcgen::SubjectPublicKeyInfo::from_der(&csr.pubkey)
7185
.context("Failed to parse signature")?;
7286
let cfg = &csr.config;
@@ -80,6 +94,7 @@ impl CaCert {
8094
.maybe_quote(cfg.ext_quote.then_some(&csr.quote))
8195
.maybe_event_log(cfg.ext_quote.then_some(&csr.event_log))
8296
.maybe_app_id(app_id)
97+
.special_usage(usage)
8398
.build();
8499
self.sign(req).context("Failed to sign certificate")
85100
}

0 commit comments

Comments
 (0)