Skip to content

Commit df0462c

Browse files
committed
attestation: move schema crate back into workspace
1 parent ac6a3d0 commit df0462c

4 files changed

Lines changed: 138 additions & 1 deletion

File tree

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ members = [
2020
"ra-tls",
2121
"tdx-attest",
2222
"dstack-attest",
23+
"dstack-attestation-types",
2324
"dstack-util",
2425
"iohash",
2526
"guest-agent",
@@ -72,6 +73,7 @@ supervisor = { path = "supervisor" }
7273
supervisor-client = { path = "supervisor/client" }
7374
tdx-attest = { path = "tdx-attest" }
7475
dstack-attest = { path = "dstack-attest" }
76+
dstack-attestation-types = { path = "dstack-attestation-types" }
7577
certbot = { path = "certbot" }
7678
rocket-vsock-listener = { path = "rocket-vsock-listener" }
7779
host-api = { path = "host-api", default-features = false }

dstack-attest/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ anyhow.workspace = true
1414
cc-eventlog.workspace = true
1515
ciborium.workspace = true
1616
dcap-qvl.workspace = true
17-
dstack-attestation-types = { path = "../../../src/attestation-types" }
17+
dstack-attestation-types.workspace = true
1818
dstack-types.workspace = true
1919
ez-hash.workspace = true
2020
fs-err.workspace = true
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "dstack-attestation-types"
3+
version.workspace = true
4+
authors.workspace = true
5+
edition.workspace = true
6+
license.workspace = true
7+
8+
[dependencies]
9+
anyhow.workspace = true
10+
ciborium.workspace = true
11+
cc-eventlog.workspace = true
12+
serde.workspace = true
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use anyhow::{bail, Context, Result};
2+
use cc_eventlog::{RuntimeEvent, TdxEvent};
3+
use serde::{Deserialize, Serialize};
4+
5+
pub const ATTESTATION_VERSION: u64 = 1;
6+
7+
#[derive(Debug, Clone, Serialize, Deserialize)]
8+
#[serde(tag = "kind")]
9+
pub enum PlatformEvidence {
10+
#[serde(rename = "tdx")]
11+
Tdx {
12+
quote: Vec<u8>,
13+
event_log: Vec<TdxEvent>,
14+
},
15+
#[serde(rename = "gcp-tdx")]
16+
GcpTdx,
17+
#[serde(rename = "nitro-enclave")]
18+
NitroEnclave,
19+
}
20+
21+
#[derive(Debug, Clone, Serialize, Deserialize)]
22+
#[serde(tag = "kind")]
23+
pub enum StackEvidence {
24+
#[serde(rename = "dstack")]
25+
Dstack {
26+
report_data: Vec<u8>,
27+
runtime_events: Vec<RuntimeEvent>,
28+
config: String,
29+
},
30+
#[serde(rename = "dstack-k8s")]
31+
DstackK8s {
32+
report_data: Vec<u8>,
33+
runtime_events: Vec<RuntimeEvent>,
34+
config: String,
35+
report_data_payload: String,
36+
},
37+
}
38+
39+
#[derive(Debug, Clone, Serialize, Deserialize)]
40+
pub struct Attestation {
41+
pub version: u64,
42+
pub platform: PlatformEvidence,
43+
pub stack: StackEvidence,
44+
}
45+
46+
impl Attestation {
47+
pub fn new(platform: PlatformEvidence, stack: StackEvidence) -> Self {
48+
Self {
49+
version: ATTESTATION_VERSION,
50+
platform,
51+
stack,
52+
}
53+
}
54+
55+
pub fn to_cbor(&self) -> Result<Vec<u8>> {
56+
let mut normalized = self.clone();
57+
normalized.version = ATTESTATION_VERSION;
58+
let mut bytes = Vec::new();
59+
ciborium::into_writer(&normalized, &mut bytes)
60+
.context("Failed to encode attestation as CBOR")?;
61+
Ok(bytes)
62+
}
63+
64+
pub fn from_cbor(bytes: &[u8]) -> Result<Self> {
65+
let value: Self =
66+
ciborium::from_reader(bytes).context("Failed to decode attestation from CBOR")?;
67+
if value.version != ATTESTATION_VERSION {
68+
bail!(
69+
"Unsupported attestation version: expected {}, got {}",
70+
ATTESTATION_VERSION,
71+
value.version
72+
);
73+
}
74+
Ok(value)
75+
}
76+
}
77+
78+
#[cfg(test)]
79+
mod tests {
80+
use super::*;
81+
82+
#[test]
83+
fn cbor_roundtrip_preserves_attestation() {
84+
let attestation = Attestation::new(
85+
PlatformEvidence::Tdx {
86+
quote: vec![1u8, 2, 3],
87+
event_log: Vec::new(),
88+
},
89+
StackEvidence::DstackK8s {
90+
report_data: vec![7u8; 64],
91+
runtime_events: Vec::new(),
92+
config: "{}".into(),
93+
report_data_payload: "{\"hello\":\"world\"}".into(),
94+
},
95+
);
96+
97+
let encoded = attestation.to_cbor().expect("encode cbor");
98+
assert!(matches!(encoded.first(), Some(0xa0..=0xbf)));
99+
let decoded = Attestation::from_cbor(&encoded).expect("decode cbor");
100+
assert_eq!(decoded.version, ATTESTATION_VERSION);
101+
match decoded.platform {
102+
PlatformEvidence::Tdx { quote, event_log } => {
103+
assert_eq!(quote, vec![1u8, 2, 3]);
104+
assert!(event_log.is_empty());
105+
}
106+
_ => panic!("expected tdx platform evidence"),
107+
}
108+
match decoded.stack {
109+
StackEvidence::DstackK8s {
110+
report_data,
111+
runtime_events,
112+
config,
113+
report_data_payload,
114+
} => {
115+
assert_eq!(report_data, vec![7u8; 64]);
116+
assert!(runtime_events.is_empty());
117+
assert_eq!(config, "{}");
118+
assert_eq!(report_data_payload, "{\"hello\":\"world\"}");
119+
}
120+
_ => panic!("expected dstack-k8s stack evidence"),
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)