50 lines
1.5 KiB
Rust
50 lines
1.5 KiB
Rust
use std::borrow::Cow;
|
|
use std::time::UNIX_EPOCH;
|
|
|
|
use chrono::Duration;
|
|
use shell_escape::escape;
|
|
use ssh_key::Certificate;
|
|
|
|
/// Generates an command to renew the given certs
|
|
pub fn renew_command(cert: &Certificate, ca_path: &str, file_name: Option<&str>) -> String {
|
|
let validity = cert
|
|
.valid_before_time()
|
|
.duration_since(cert.valid_after_time())
|
|
.unwrap_or(Duration::zero().to_std().unwrap());
|
|
let expiry = cert.valid_before_time().checked_add(validity).unwrap();
|
|
let expiry_date = expiry.duration_since(UNIX_EPOCH).unwrap();
|
|
let host_key = if cert.cert_type().is_host() {
|
|
" -h"
|
|
} else {
|
|
""
|
|
};
|
|
let opts = cert
|
|
.critical_options()
|
|
.iter()
|
|
.map(|(opt, val)| {
|
|
if val.is_empty() {
|
|
opt.clone()
|
|
} else {
|
|
format!("{opt}={val}")
|
|
}
|
|
})
|
|
.map(|arg| format!("-O {}", escape(arg.into())))
|
|
.collect::<Vec<_>>()
|
|
.join(" ");
|
|
let opts = opts.trim();
|
|
let renew_command = format!(
|
|
"ssh-keygen -s {ca_path} {host_key} -I {} -n {} -z {} -V {}:{} {opts} {}",
|
|
escape(cert.key_id().into()),
|
|
escape(cert.valid_principals().join(",").into()),
|
|
cert.serial() + 1,
|
|
cert.valid_after(),
|
|
expiry_date.as_secs(),
|
|
escape(
|
|
file_name
|
|
.map(|name| name.trim_end_matches("-cert.pub")).map(Cow::Borrowed)
|
|
.unwrap_or_else(|| escape(format!("{}.pub", cert.key_id()).into()))
|
|
)
|
|
);
|
|
renew_command
|
|
}
|