use std::path::Path;
const CA_KEY: &str = "ca.key";
const CURVE: &str = "ec_paramgen_curve:P-256";
const DAYS: &str = "1";
pub(crate) const FOOT: &str = "foot";
pub(crate) const FOOT_NAME: &str = "thrall-test-foot";
pub(crate) const OPERATOR_NAME: &str = "thrall-test-operator";
pub(crate) const NAMELESS: &str = "nameless";
pub(crate) const ENGINE: &str = "engine";
pub(crate) fn material(dir: &Path) {
std::fs::create_dir_all(dir).expect("the scratch directory");
ca(dir);
leaf(
dir,
ENGINE,
&format!("/CN={ENGINE}"),
"IP:127.0.0.1",
"serverAuth",
);
leaf(
dir,
"client",
&format!("/OU={FOOT}/CN={FOOT_NAME}"),
&format!("DNS:{FOOT_NAME}"),
"clientAuth",
);
leaf(
dir,
OPERATOR_NAME,
&format!("/CN={OPERATOR_NAME}"),
&format!("DNS:{OPERATOR_NAME}"),
"clientAuth",
);
leaf(
dir,
NAMELESS,
&format!("/OU={FOOT}"),
&format!("DNS:{NAMELESS}"),
"clientAuth",
);
}
pub(crate) fn provisioned(dir: &Path, address: &str) -> crate::channel::material::Material {
material(dir);
std::fs::write(dir.join(crate::channel::material::ADDRESS), address).expect("the address");
crate::channel::material::read_dir(dir)
.expect("readable")
.expect("provisioned")
}
fn ca(dir: &Path) {
tool(&[
"req",
"-x509",
"-newkey",
"ec",
"-pkeyopt",
CURVE,
"-nodes",
"-sha256",
"-days",
DAYS,
"-subj",
"/CN=thrall-test-ca",
"-keyout",
&path(dir, CA_KEY),
"-out",
&path(dir, crate::channel::material::ANCHORS),
]);
}
fn leaf(dir: &Path, name: &str, subject: &str, san: &str, eku: &str) {
let ext = dir.join(format!("{name}.ext"));
std::fs::write(
&ext,
format!("[leaf]\nsubjectAltName={san}\nextendedKeyUsage={eku}\n"),
)
.expect("the extension file");
tool(&[
"req",
"-new",
"-newkey",
"ec",
"-pkeyopt",
CURVE,
"-nodes",
"-sha256",
"-subj",
subject,
"-keyout",
&path(dir, &format!("{name}.key")),
"-out",
&path(dir, &format!("{name}.csr")),
]);
tool(&[
"x509",
"-req",
"-sha256",
"-days",
DAYS,
"-extfile",
&ext.to_string_lossy(),
"-extensions",
"leaf",
"-in",
&path(dir, &format!("{name}.csr")),
"-CA",
&path(dir, crate::channel::material::ANCHORS),
"-CAkey",
&path(dir, CA_KEY),
"-CAcreateserial",
"-out",
&path(dir, &format!("{name}.pem")),
]);
}
fn path(dir: &Path, leaf: &str) -> String {
dir.join(leaf).to_string_lossy().into_owned()
}
fn tool(args: &[&str]) {
let mut cmd = crate::spawn::command("openssl");
cmd.args(args);
let said = crate::spawn::output(&mut cmd).expect("openssl is installed");
assert!(
said.status.success(),
"openssl {args:?}: {}",
String::from_utf8_lossy(&said.stderr)
);
}