Skip to content

Commit 0df913c

Browse files
committed
wip: add code to have cargo generate mock data
This isn't entirely necessary but it's convenient. The `demo-vm.sh` script generates these files for itself. Nothing built by cargo needs this ... yet but this will be necessary for integration tests.
1 parent 06a78be commit 0df913c

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name = "vm-attest-demo"
33
version = "0.1.0"
44
edition = "2024"
5+
build = "build/main.rs"
56

67
[dependencies]
78
anyhow = "1.0.102"
@@ -21,3 +22,6 @@ thiserror = "2.0.18"
2122
vm-attest = { git = "https://github.com/oxidecomputer/vm-attest", rev = "f2184012395b329b09395d1a63a1961a267d1166" }
2223
vsock = "0.5.3"
2324
x509-cert = "0.2.5"
25+
26+
[build-dependencies]
27+
anyhow = "1.0.102"

build/main.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use anyhow::{Context, Result};
6+
7+
mod test_data;
8+
9+
fn main() -> Result<()> {
10+
test_data::generate().context("generate mock data for testing")?;
11+
12+
Ok(())
13+
}

build/test_data.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use anyhow::Result;
6+
use anyhow::{Context, anyhow};
7+
use std::env;
8+
use std::fs::{self, File};
9+
use std::io::Write;
10+
use std::path::{self, Path, PathBuf};
11+
12+
/// Execute one of the `pki-playground` commands to generate part of the PKI
13+
/// used for testing.
14+
fn pki_gen_cmd(command: &str, cfg: &Path) -> Result<()> {
15+
if !fs::exists(cfg).with_context(|| {
16+
format!("failed to determin if file exists: {}", cfg.display())
17+
})? {
18+
return Err(anyhow!("missing PKI config file: {}", cfg.display()));
19+
}
20+
21+
let mut cmd = std::process::Command::new("pki-playground");
22+
cmd.arg("--config");
23+
cmd.arg(cfg);
24+
cmd.arg(command);
25+
let output = cmd
26+
.output()
27+
.context("executing command \"pki-playground\"")?;
28+
29+
if !output.status.success() {
30+
let stdout = String::from_utf8(output.stdout)
31+
.context("String from pki-playground stdout")?;
32+
println!("stdout: {stdout}");
33+
let stderr = String::from_utf8(output.stderr)
34+
.context("String from pki-playground stderr")?;
35+
println!("stderr: {stderr}");
36+
37+
return Err(anyhow!("cmd failed: {cmd:?}"));
38+
}
39+
40+
Ok(())
41+
}
42+
43+
/// Execute one of the `attest-mock` commands to generate mock input data used
44+
/// for testing.
45+
fn attest_gen_cmd(command: &str, input: &Path, output: &str) -> Result<()> {
46+
if !fs::exists(input).with_context(|| {
47+
format!("failed to determin if file exists: {}", input.display())
48+
})? {
49+
return Err(anyhow!("missing config file: {}", input.display()));
50+
}
51+
52+
// attest-mock "input" "cmd" > "output"
53+
let mut cmd = std::process::Command::new("attest-mock");
54+
cmd.arg(input).arg(command);
55+
let cmd_output =
56+
cmd.output().context("executing command \"attest-mock\"")?;
57+
58+
if cmd_output.status.success() {
59+
std::fs::write(output, cmd_output.stdout).context("write {output}")
60+
} else {
61+
let stderr = String::from_utf8(cmd_output.stderr)
62+
.context("String from attest-mock stderr")?;
63+
println!("stderr: {stderr}");
64+
65+
Err(anyhow!("cmd failed: {cmd:?}"))
66+
}
67+
}
68+
69+
fn write_path_to_conf(mut file: &File, path: &Path, name: &str) -> Result<()> {
70+
if !fs::exists(path).with_context(|| {
71+
format!("checking existance of file: {}", path.display())
72+
})? {
73+
return Err(anyhow!("required file not present: {}", path.display()));
74+
}
75+
76+
Ok(writeln!(
77+
file,
78+
"#[allow(dead_code)]\npub const {}: &str =\n \"{}\";\n",
79+
name,
80+
path.display(),
81+
)?)
82+
}
83+
84+
pub fn generate() -> Result<()> {
85+
let cwd = env::current_dir().context("get current dir")?;
86+
let mut cwd = path::absolute(cwd).context("current_dir to absolute")?;
87+
88+
// output directory where we put:
89+
// generated test inputs
90+
let mut out =
91+
PathBuf::from(env::var("OUT_DIR").context("Could not get OUT_DIR")?);
92+
env::set_current_dir(&out)
93+
.with_context(|| format!("chdir to {}", out.display()))?;
94+
95+
// paths consumed by the library as const `&str`s go here
96+
out.push("config.rs");
97+
let config_out = File::create(&out)
98+
.with_context(|| format!("creating {}", out.display()))?;
99+
out.pop();
100+
101+
cwd.push("test-data");
102+
cwd.push("config.kdl");
103+
let mut pki_cfg = cwd;
104+
// generate keys
105+
pki_gen_cmd("generate-key-pairs", &pki_cfg)?;
106+
out.push("test-alias.key.pem");
107+
write_path_to_conf(&config_out, &out, "ATTESTATION_SIGNER")
108+
.context("write variable w/ path to attestation signing key")?;
109+
out.pop();
110+
111+
// generate certs
112+
pki_gen_cmd("generate-certificates", &pki_cfg)?;
113+
out.push("test-root.cert.pem");
114+
write_path_to_conf(&config_out, &out, "PKI_ROOT")
115+
.context("write PKI_ROOT const str to config.rs")?;
116+
out.pop();
117+
118+
// generate cert chains
119+
pki_gen_cmd("generate-certificate-lists", &pki_cfg)?;
120+
pki_cfg.pop();
121+
out.push("test-alias.certlist.pem");
122+
write_path_to_conf(&config_out, &out, "SIGNER_PKIPATH")
123+
.context("write variable w/ path to attestation signing key")?;
124+
out.pop();
125+
126+
// generate measurement log
127+
let mut log_cfg = pki_cfg;
128+
log_cfg.push("log.kdl");
129+
attest_gen_cmd("log", &log_cfg, "log.bin")?;
130+
log_cfg.pop();
131+
132+
out.push("log.bin");
133+
write_path_to_conf(&config_out, &out, "LOG")
134+
.context("write variable w/ path to attestation signing key")?;
135+
out.pop();
136+
137+
// generate the corpus of reference measurements
138+
let mut corim_cfg = log_cfg;
139+
corim_cfg.push("corim.kdl");
140+
attest_gen_cmd("corim", &corim_cfg, "corim.cbor")?;
141+
corim_cfg.pop();
142+
143+
out.push("corim.cbor");
144+
write_path_to_conf(&config_out, &out, "CORIM").context(
145+
"write variable w/ path to reference integrity measurements",
146+
)?;
147+
out.pop();
148+
149+
let mut vm_instance_cfg = corim_cfg;
150+
vm_instance_cfg.push("vm-instance-cfg.json");
151+
write_path_to_conf(&config_out, &vm_instance_cfg, "VM_INSTANCE_CFG")
152+
.context(
153+
"write variable w/ path to data attested by the InstanceRoT",
154+
)?;
155+
vm_instance_cfg.pop();
156+
157+
Ok(())
158+
}

0 commit comments

Comments
 (0)