use std::path::Path;
use crate::registry::enroll::Request;
use crate::registry::{Grade, leaf};
use crate::wire::provision;
pub(super) fn mint_or_adopt(dir: &Path, request: &Request) -> Result<Grade, String> {
let cert = dir.join(format!("{}.pem", request.name));
let key = dir.join(format!("{}.key", request.name));
match (cert.is_file(), key.is_file()) {
(false, false) => {
provision::issue(dir, &request.name, request.grade).map(|()| request.grade)
}
(true, true) => adopt(&cert, request),
(true, false) => Err(format!(
"{} was enrolled already: its key left this box with that enrollment, so there is no \
material to hand over a second time and re-issuing would put two live certificates \
under one identity. The device is registered where it was enrolled; to seat it in \
another workspace, write the registration on this box — `mkdir -p \
<state-root>/{}/{}/{} && touch …/{}` — no gesture manages registrations, on \
this engine or any other. State another common name to enrol a second device",
request.name,
crate::registry::CLIENTS,
request.name,
crate::registry::WORKSPACES,
request.workspace
)),
(false, true) => Err(format!(
"{}: a key with no certificate beside it — debris from a mint that did not finish. \
Remove it and enrol again",
key.display()
)),
}
}
fn adopt(cert: &Path, request: &Request) -> Result<Grade, String> {
let grade = leaf::grade_at(cert)?;
if grade == request.grade {
return Ok(grade);
}
Err(format!(
"{} is already here and is {} grade, but this enrollment asks for {}: a grade is minted \
into the subject by the operator's own CA, so registering a certificate cannot change \
what it says. Enrol it as {}, or state another common name and mint a fresh leaf",
cert.display(),
grade.word(),
request.grade.word(),
grade.word()
))
}