use super::super::{ANCHORS, LOOPBACK, PORT};
use super::{Act, Plan, READS, SUBCMD};
use crate::registry::Grade;
use crate::wire::material::{ADDRESS, DIR, ENTRIES, ENTRY, Role};
use std::path::Path;
pub fn perform(plan: &Plan) -> i32 {
match &plan.act {
Act::Mint { hosts, port, force } => mint(&plan.dir, hosts, port.as_deref(), *force),
Act::Leaf(cn, grade) => leaf(&plan.dir, cn, *grade),
}
}
fn mint(dir: &Path, hosts: &[String], port: Option<&str>, force: bool) -> i32 {
if dir.join(ANCHORS).is_file() && !force {
if hosts.is_empty() {
eprintln!(
"yog {SUBCMD}: {} already holds material; rotating distrusts every certificate \
already issued. Re-run with FORCE=1 if that is what you mean, or state \
{}=<host>[,<host>…] {}=<port> to say where this engine listens — which \
re-issues the server leaf and writes the address, over the CA already here, \
distrusting nothing.",
dir.display(),
READS[1],
READS[2]
);
return 1;
}
return restate(dir, hosts, port);
}
let address = format!(
"{}:{}",
hosts.first().map_or(LOOPBACK, String::as_str),
port.unwrap_or(PORT)
);
match super::super::mint(dir, &address, hosts.get(1..).unwrap_or_default(), force) {
Ok(()) => {
report(dir, &address);
0
}
Err(e) => {
eprintln!("yog {SUBCMD}: {e}");
1
}
}
}
fn restate(dir: &Path, hosts: &[String], port: Option<&str>) -> i32 {
let standing = super::super::port_at(dir);
let address = format!(
"{}:{}",
hosts.first().map_or(LOOPBACK, String::as_str),
port.unwrap_or(&standing)
);
let acted = super::super::reissue(dir, hosts).and_then(|()| super::super::state(dir, &address));
if let Err(e) = acted {
eprintln!("yog {SUBCMD}: {e}");
return 1;
}
let leaf = Role::Server.leaf();
println!(
"yog {SUBCMD}: re-issued the {leaf} leaf over the CA already in {}",
dir.display()
);
for name in [format!("{leaf}.pem"), format!("{leaf}.key")] {
println!(" {}", dir.join(name).display());
}
println!(" it answers to {}", hosts.join(", "));
println!(
" {} names {address} — restart the engine, which binds it as it starts",
dir.join(ADDRESS).display()
);
println!(" the CA is untouched, so every leaf already issued still verifies");
0
}
fn leaf(dir: &Path, cn: &str, grade: Grade) -> i32 {
if let Err(e) = super::super::issue(dir, cn, grade) {
eprintln!("yog {SUBCMD}: {e}");
return 1;
}
println!("yog {SUBCMD}: issued a {} leaf for {cn}", word(grade));
for name in [format!("{cn}.pem"), format!("{cn}.key")] {
println!(" {}", dir.join(name).display());
}
let client = Role::Client.leaf();
println!(
" carry those and {} to that box by hand, into its {DIR}/{ENTRIES}/{ENTRY}/ — named for \
the WORKSPACE it will address, not for {cn} — as {client}.pem, {client}.key and \
{ANCHORS}, beside an {ADDRESS} you state; the common name inside, not the basename, is \
the identity",
dir.join(ANCHORS).display()
);
println!(
" {cn} is registered in NO workspace: enrol the same common name from a seat in the \
workspace it should serve (`/enroll {cn}{}`), which adopts this leaf rather than \
issuing a second one",
match grade {
Grade::Operator => String::new(),
Grade::Foot => format!(" {}", crate::registry::peer::FOOT),
}
);
0
}
fn report(dir: &Path, address: &str) {
println!(
"yog {SUBCMD}: {} holds {}",
dir.display(),
super::super::artifacts(address).join(", ")
);
println!(" the engine binds and a local seat dials {address}");
println!(
" issue another client with: WIRE_LEAF=<common-name> yog {SUBCMD}, and a tool host's \
with {}=1 beside that",
READS[5]
);
}
pub(super) fn word(grade: Grade) -> &'static str {
match grade {
Grade::Operator => "client",
Grade::Foot => crate::registry::peer::FOOT,
}
}