use super::super::{CA_KEY, ensure, issue};
use super::described;
use crate::git_env;
use crate::registry::{Grade, LOCAL};
use crate::wire::material::{ADDRESS, ANCHORS, Role, read_dir};
use std::path::Path;
use tempfile::TempDir;
const VISITOR: &str = "phone";
#[test]
fn a_host_issues_a_client_leaf_under_the_name_it_states() {
let tmp = TempDir::new().expect("tmp");
let dir = tmp.path().join("wire");
ensure(&dir).expect("mint");
issue(&dir, VISITOR, Grade::Operator).expect("issue");
let pem = dir.join(format!("{VISITOR}.pem"));
assert!(dir.join(format!("{VISITOR}.key")).is_file(), "the key too");
assert!(
described(&pem, &["-subject"]).contains(&format!("CN={VISITOR}")),
"the stated name is the subject: {}",
described(&pem, &["-subject"])
);
let text = described(&pem, &["-text"]);
assert!(
text.contains("TLS Web Client Authentication"),
"a client leaf authenticates as a client: {text}"
);
assert!(
text.contains(&format!("DNS:{VISITOR}")),
"and its SAN names itself: {text}"
);
assert!(
!text.contains("TLS Web Server Authentication") && !text.contains("IP Address"),
"no server EKU and no host anywhere in it: {text}"
);
let ca = dir.join(ANCHORS).to_string_lossy().into_owned();
let out = git_env::output(git_env::command(Path::new("openssl")).args([
"verify",
"-CAfile",
&ca,
&pem.to_string_lossy(),
]))
.expect("openssl");
assert!(out.status.success(), "the CA already here signed it");
}
#[test]
fn the_pair_reads_back_as_an_entry_on_the_box_it_is_carried_to() {
let host = TempDir::new().expect("tmp");
ensure(host.path()).expect("mint");
issue(host.path(), VISITOR, Grade::Operator).expect("issue");
let visitor = TempDir::new().expect("tmp");
let entry = visitor.path().join("workspaces").join(VISITOR);
std::fs::create_dir_all(&entry).expect("entry");
for (from, to) in [
(format!("{VISITOR}.pem"), "client.pem"),
(format!("{VISITOR}.key"), "client.key"),
(ANCHORS.to_owned(), ANCHORS),
] {
std::fs::copy(host.path().join(from), entry.join(to)).expect("carried by hand");
}
std::fs::write(entry.join(ADDRESS), "engine.example.com:7737\n").expect("stated address");
let material = read_dir(&entry, Role::Client)
.expect("readable")
.expect("provisioned");
assert_eq!(material.address, "engine.example.com:7737");
assert_eq!(material.chain, entry.join("client.pem"));
assert!(
described(&material.chain, &["-subject"]).contains(&format!("CN={VISITOR}")),
"the common name inside, not the basename, is the identity"
);
}
#[test]
fn a_box_with_no_ca_key_refuses_and_says_which_file() {
let tmp = TempDir::new().expect("tmp");
let bare = tmp.path().join("bare");
std::fs::create_dir_all(&bare).expect("dir");
let refusal = issue(&bare, VISITOR, Grade::Operator).expect_err("nothing to sign with");
assert!(refusal.contains(CA_KEY), "{refusal}");
let client = tmp.path().join("client-box");
std::fs::create_dir_all(&client).expect("dir");
std::fs::write(client.join(ANCHORS), b"operator's own").expect("anchor");
let refusal =
issue(&client, VISITOR, Grade::Operator).expect_err("a client machine cannot issue");
assert!(refusal.contains(CA_KEY), "{refusal}");
assert_eq!(
std::fs::read(client.join(ANCHORS)).expect("anchor"),
b"operator's own",
"and the operator's trust root is untouched"
);
assert!(!client.join(format!("{VISITOR}.pem")).is_file());
}
#[test]
fn an_existing_pair_refuses_and_names_its_remedy() {
let tmp = TempDir::new().expect("tmp");
ensure(tmp.path()).expect("mint");
issue(tmp.path(), VISITOR, Grade::Operator).expect("issue");
let first = std::fs::read(tmp.path().join(format!("{VISITOR}.pem"))).expect("leaf");
let refusal = issue(tmp.path(), VISITOR, Grade::Operator).expect_err("already issued");
assert!(refusal.contains("FORCE=1"), "{refusal}");
assert_eq!(
std::fs::read(tmp.path().join(format!("{VISITOR}.pem"))).expect("leaf"),
first,
"and refused without touching it"
);
std::fs::remove_file(tmp.path().join(format!("{VISITOR}.pem"))).expect("rm");
assert!(
issue(tmp.path(), VISITOR, Grade::Operator).is_err(),
"the key is still here"
);
std::fs::remove_file(tmp.path().join(format!("{VISITOR}.key"))).expect("rm");
issue(tmp.path(), VISITOR, Grade::Operator).expect("a name nothing holds");
}
#[test]
fn an_identity_the_registry_would_refuse_is_refused_here() {
let tmp = TempDir::new().expect("tmp");
ensure(tmp.path()).expect("mint");
for name in ["", ".", "..", "a/b", "a\\b", "a\0b", LOCAL] {
let refusal = issue(tmp.path(), name, Grade::Operator).expect_err("unusable");
assert!(refusal.contains(LOCAL), "{name:?} → {refusal}");
assert_eq!(
std::fs::read_dir(tmp.path()).expect("dir").count(),
super::super::artifacts().len(),
"{name:?} wrote something"
);
}
}