Skip to content

Commit 029f167

Browse files
committed
Add CertConfigV2
1 parent 70720d5 commit 029f167

7 files changed

Lines changed: 78 additions & 19 deletions

File tree

cert-client/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use dstack_types::{AppKeys, KeyProvider};
88
use ra_rpc::client::{RaClient, RaClientConfig};
99
use ra_tls::{
1010
attestation::{QuoteContentType, VersionedAttestation},
11-
cert::{generate_ra_cert, CaCert, CertConfig, CertSigningRequestV2, Csr},
11+
cert::{generate_ra_cert, CaCert, CertConfigV2, CertSigningRequestV2, Csr},
1212
rcgen::KeyPair,
1313
};
1414

@@ -96,7 +96,7 @@ impl CertRequestClient {
9696
pub async fn request_cert(
9797
&self,
9898
key: &KeyPair,
99-
config: CertConfig,
99+
config: CertConfigV2,
100100
attestation_override: Option<VersionedAttestation>,
101101
) -> Result<Vec<String>> {
102102
let pubkey = key.public_key_der();

dstack-util/src/system_setup.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use luks2::{
2828
LuksSegmentSize,
2929
};
3030
use ra_rpc::client::{CertInfo, RaClient, RaClientConfig};
31-
use ra_tls::cert::generate_ra_cert;
31+
use ra_tls::cert::{generate_ra_cert, CertConfigV2};
3232
use rand::Rng as _;
3333
use scopeguard::defer;
3434
use serde::{Deserialize, Serialize};
@@ -48,10 +48,7 @@ use cmd_lib::run_fun as cmd;
4848
use dstack_gateway_rpc::{
4949
gateway_client::GatewayClient, RegisterCvmRequest, RegisterCvmResponse, WireGuardPeer,
5050
};
51-
use ra_tls::{
52-
cert::CertConfig,
53-
rcgen::{KeyPair, PKCS_ECDSA_P256_SHA256},
54-
};
51+
use ra_tls::rcgen::{KeyPair, PKCS_ECDSA_P256_SHA256};
5552
use serde_human_bytes as hex_bytes;
5653
use serde_json::Value;
5754

@@ -388,13 +385,15 @@ impl<'a> GatewayContext<'a> {
388385
let sk = cmd!(wg genkey)?;
389386
let pk = cmd!(echo $sk | wg pubkey).or(Err(anyhow!("Failed to generate public key")))?;
390387

391-
let config = CertConfig {
388+
let config = CertConfigV2 {
392389
org_name: None,
393390
subject: "dstack-guest-agent".to_string(),
394391
subject_alt_names: vec![],
395392
usage_server_auth: false,
396393
usage_client_auth: true,
397394
ext_quote: true,
395+
not_before: None,
396+
not_after: None,
398397
};
399398
let cert_client = CertRequestClient::create(
400399
self.keys,

gateway/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ async fn maybe_gen_certs(config: &Config, tls_config: &TlsConfig) -> Result<()>
7777
usage_ra_tls: true,
7878
usage_server_auth: true,
7979
usage_client_auth: false,
80+
not_before: None,
81+
not_after: None,
8082
})
8183
.await?;
8284

gateway/src/main_service/sync_client.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ pub(crate) async fn sync_task(proxy: Proxy) -> Result<()> {
9090
usage_ra_tls: false,
9191
usage_server_auth: false,
9292
usage_client_auth: true,
93+
not_after: None,
94+
not_before: None,
9395
})
9496
.await
9597
.context("Failed to get sync-client keys")?;

guest-agent/rpc/proto/agent_rpc.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ message GetTlsKeyArgs {
7272
bool usage_server_auth = 4;
7373
// Key usage client auth
7474
bool usage_client_auth = 5;
75+
// Certificate validity start time as seconds since UNIX epoch
76+
optional uint64 not_before = 6;
77+
// Certificate validity end time as seconds since UNIX epoch
78+
optional uint64 not_after = 7;
7579
}
7680

7781
// The request to derive a key

guest-agent/src/rpc_service.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use or_panic::ResultOrPanic;
2929
use ra_rpc::{Attestation, CallContext, RpcCall};
3030
use ra_tls::{
3131
attestation::{QuoteContentType, VersionedAttestation, DEFAULT_HASH_ALGORITHM},
32-
cert::CertConfig,
32+
cert::CertConfigV2,
3333
kdf::{derive_ecdsa_key, derive_ecdsa_key_pair_from_bytes},
3434
};
3535
use rcgen::KeyPair;
@@ -78,13 +78,15 @@ impl AppStateInner {
7878
.cert_client
7979
.request_cert(
8080
&key,
81-
CertConfig {
81+
CertConfigV2 {
8282
org_name: None,
8383
subject: "demo-cert".to_string(),
8484
subject_alt_names: vec![],
8585
usage_server_auth: false,
8686
usage_client_auth: true,
8787
ext_quote: true,
88+
not_after: None,
89+
not_before: None,
8890
},
8991
attestation_override,
9092
)
@@ -233,13 +235,15 @@ impl DstackGuestRpc for InternalRpcHandler {
233235
.context("Failed to generate secure seed")?;
234236
let derived_key =
235237
derive_ecdsa_key_pair_from_bytes(&seed, &[]).context("Failed to derive key")?;
236-
let config = CertConfig {
238+
let config = CertConfigV2 {
237239
org_name: None,
238240
subject: request.subject,
239241
subject_alt_names: request.alt_names,
240242
usage_server_auth: request.usage_server_auth,
241243
usage_client_auth: request.usage_client_auth,
242244
ext_quote: request.usage_ra_tls,
245+
not_after: request.not_after,
246+
not_before: request.not_before,
243247
};
244248
let attestation_override = self
245249
.state
@@ -493,13 +497,15 @@ impl TappdRpc for InternalRpcHandlerV0 {
493497
};
494498
let derived_key = derive_ecdsa_key_pair_from_bytes(seed, &[request.path.as_bytes()])
495499
.context("Failed to derive key")?;
496-
let config = CertConfig {
500+
let config = CertConfigV2 {
497501
org_name: None,
498502
subject: request.subject,
499503
subject_alt_names: request.alt_names,
500504
usage_server_auth: request.usage_server_auth,
501505
usage_client_auth: request.usage_client_auth,
502506
ext_quote: request.usage_ra_tls,
507+
not_before: None,
508+
not_after: None,
503509
};
504510
let attestation_override = self
505511
.state

ra-tls/src/cert.rs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
//! Certificate creation functions.
66
7-
use std::time::SystemTime;
7+
use std::time::{SystemTime, UNIX_EPOCH};
88
use std::{path::Path, time::Duration};
99

1010
use anyhow::{anyhow, bail, Context, Result};
@@ -99,6 +99,8 @@ impl CaCert {
9999
.maybe_attestation(attestation)
100100
.maybe_app_id(app_id)
101101
.special_usage(usage)
102+
.maybe_not_before(cfg.not_before.map(unix_time_to_system_time))
103+
.maybe_not_after(cfg.not_after.map(unix_time_to_system_time))
102104
.build();
103105
self.sign(req).context("Failed to sign certificate")
104106
}
@@ -121,6 +123,42 @@ pub struct CertConfig {
121123
pub ext_quote: bool,
122124
}
123125

126+
/// The configuration of the certificate with optional validity overrides.
127+
#[derive(Encode, Decode, Clone, PartialEq)]
128+
pub struct CertConfigV2 {
129+
/// The organization name of the certificate.
130+
pub org_name: Option<String>,
131+
/// The subject of the certificate.
132+
pub subject: String,
133+
/// The subject alternative names of the certificate.
134+
pub subject_alt_names: Vec<String>,
135+
/// The purpose of the certificate.
136+
pub usage_server_auth: bool,
137+
/// The purpose of the certificate.
138+
pub usage_client_auth: bool,
139+
/// Whether the certificate is quoted.
140+
pub ext_quote: bool,
141+
/// The certificate validity start time as seconds since UNIX epoch.
142+
pub not_before: Option<u64>,
143+
/// The certificate validity end time as seconds since UNIX epoch.
144+
pub not_after: Option<u64>,
145+
}
146+
147+
impl From<CertConfig> for CertConfigV2 {
148+
fn from(config: CertConfig) -> Self {
149+
Self {
150+
org_name: config.org_name,
151+
subject: config.subject,
152+
subject_alt_names: config.subject_alt_names,
153+
usage_server_auth: config.usage_server_auth,
154+
usage_client_auth: config.usage_client_auth,
155+
ext_quote: config.ext_quote,
156+
not_before: None,
157+
not_after: None,
158+
}
159+
}
160+
}
161+
124162
/// A certificate signing request.
125163
#[derive(Encode, Decode, Clone)]
126164
pub struct CertSigningRequestV1 {
@@ -240,7 +278,7 @@ pub struct CertSigningRequestV2 {
240278
/// The public key of the certificate.
241279
pub pubkey: Vec<u8>,
242280
/// The certificate configuration.
243-
pub config: CertConfig,
281+
pub config: CertConfigV2,
244282
/// The attestation.
245283
pub attestation: VersionedAttestation,
246284
}
@@ -251,7 +289,7 @@ impl TryFrom<CertSigningRequestV1> for CertSigningRequestV2 {
251289
Ok(Self {
252290
confirm: v0.confirm,
253291
pubkey: v0.pubkey,
254-
config: v0.config,
292+
config: v0.config.into(),
255293
attestation: Attestation::from_tdx_quote(v0.quote, &v0.event_log)?.into_versioned(),
256294
})
257295
}
@@ -381,6 +419,10 @@ fn add_ext(params: &mut CertificateParams, oid: &[u64], content: impl AsRef<[u8]
381419
.push(CustomExtension::from_oid_content(oid, content));
382420
}
383421

422+
fn unix_time_to_system_time(secs: u64) -> SystemTime {
423+
UNIX_EPOCH + Duration::from_secs(secs)
424+
}
425+
384426
impl CertRequest<'_, KeyPair> {
385427
/// Create a self-signed certificate.
386428
pub fn self_signed(self) -> Result<Certificate> {
@@ -624,13 +666,15 @@ mod tests {
624666
let csr = CertSigningRequestV2 {
625667
confirm: "please sign cert:".to_string(),
626668
pubkey: vec![1, 2, 3],
627-
config: CertConfig {
669+
config: CertConfigV2 {
628670
org_name: None,
629671
subject: "test.example.com".to_string(),
630672
subject_alt_names: vec![],
631673
usage_server_auth: true,
632674
usage_client_auth: false,
633675
ext_quote: false,
676+
not_before: None,
677+
not_after: None,
634678
},
635679
attestation: Attestation {
636680
quote: AttestationQuote::DstackTdx(TdxQuote {
@@ -646,7 +690,7 @@ mod tests {
646690
};
647691

648692
let actual = hex::encode(csr.encode());
649-
let expected = "44706c65617365207369676e20636572743a0c0102030040746573742e6578616d706c652e636f6d0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
693+
let expected = "44706c65617365207369676e20636572743a0c0102030040746573742e6578616d706c652e636f6d00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
650694
assert_eq!(actual, expected);
651695
}
652696

@@ -655,13 +699,15 @@ mod tests {
655699
let csr = CertSigningRequestV2 {
656700
confirm: "please sign cert:".to_string(),
657701
pubkey: vec![1, 2, 3],
658-
config: CertConfig {
702+
config: CertConfigV2 {
659703
org_name: None,
660704
subject: "test.example.com".to_string(),
661705
subject_alt_names: vec![],
662706
usage_server_auth: true,
663707
usage_client_auth: false,
664708
ext_quote: true,
709+
not_before: None,
710+
not_after: None,
665711
},
666712
attestation: Attestation {
667713
quote: AttestationQuote::DstackTdx(TdxQuote {
@@ -677,7 +723,7 @@ mod tests {
677723
};
678724

679725
let actual = hex::encode(csr.encode());
680-
let expected = "44706c65617365207369676e20636572743a0c0102030040746573742e6578616d706c652e636f6d000100010000040900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
726+
let expected = "44706c65617365207369676e20636572743a0c0102030040746573742e6578616d706c652e636f6d0001000100000000040900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
681727
assert_eq!(actual, expected);
682728
}
683729
}

0 commit comments

Comments
 (0)