use std::io::Write;
use std::path::PathBuf;
use clap::Args;
use pointbreak::keys::{KeyName, parse_ssh_ed25519_public_key, write_agent_reference};
use crate::cli::{json, output};
#[derive(Debug, Args)]
pub(super) struct UseSshArgs {
key: String,
#[arg(long, default_value = "default")]
name: String,
#[command(flatten)]
format_args: output::FormatArgs,
}
#[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
struct UseSshBody {
name: String,
did_key: String,
path: PathBuf,
}
pub(super) fn run(
args: UseSshArgs,
stdout: &mut dyn Write,
) -> Result<(), Box<dyn std::error::Error>> {
let key_text = if args.key.starts_with("key::") {
args.key.clone()
} else {
std::fs::read_to_string(&args.key)
.map_err(|error| format!("read public key {}: {error}", args.key))?
};
let signer_id = parse_ssh_ed25519_public_key(&key_text)?;
let public_key = signer_id.ed25519_public_key()?;
let name = KeyName::parse(&args.name)?;
let handle = write_agent_reference(name.as_str(), public_key)?;
let body = UseSshBody {
name: args.name,
did_key: handle.signer_id().as_str().to_owned(),
path: handle.private_key_path().to_owned(),
};
let document = json::DiagnosticDocument::new("pointbreak.key-use-ssh", body, vec![]);
let format = output::resolve_format(args.format_args.explicit(), output::OutputFormat::Json)?;
output::write_document_json_fallback(stdout, format, &document)?;
eprintln!(
"shore: adopted SSH key as {} ({}); run `shore key enroll` to stage trust",
handle.name(),
handle.signer_id().as_str()
);
Ok(())
}