use std::fs;
use std::io::Write as _;
use std::path::Path;
use std::process::Command;
use anyhow::Context as _;
use clap::Args;
use mk_lib::file::ToUtf8 as _;
use crate::secrets::context::Context;
use super::KEY_LOCATION_HELP;
#[derive(Debug, Args)]
pub struct ImportKey {
#[arg(
long,
help = "GPG key ID or fingerprint from your local keyring (e.g. a YubiKey-backed key)"
)]
gpg: String,
#[arg(short, long, help = KEY_LOCATION_HELP)]
location: Option<String>,
#[arg(short, long, help = "The key name")]
name: Option<String>,
}
impl ImportKey {
pub fn execute(&self, context: &Context) -> anyhow::Result<()> {
let location: &str = &self.location.clone().unwrap_or_else(|| context.keys_location());
let name: &str = &self.name.clone().unwrap_or("default".to_string());
let gpg_key_id: &str = &self.gpg;
println!("Importing GPG key '{gpg_key_id}' as '{name}' into {location}");
let check = Command::new("gpg")
.args(["--batch", "--list-keys", gpg_key_id])
.output()
.context("Failed to run gpg — is it installed and available in PATH?")?;
if !check.status.success() {
let stderr = String::from_utf8_lossy(&check.stderr);
anyhow::bail!("GPG key '{}' not found in keyring: {}", gpg_key_id, stderr.trim());
}
let location_path = Path::new(location);
if !location_path.exists() {
fs::create_dir_all(location_path)?;
}
let meta_path = location_path.join(format!("{name}.gpg"));
let mut meta_file = fs::File::create(&meta_path)?;
writeln!(meta_file, "{gpg_key_id}")?;
meta_file.flush()?;
println!("Key reference saved to {}", meta_path.to_utf8()?);
let pub_path = location_path.join(format!("{name}.pub"));
let export = Command::new("gpg")
.args(["--batch", "--export", "--armor", gpg_key_id])
.output()
.context("Failed to export GPG public key")?;
if !export.status.success() {
let stderr = String::from_utf8_lossy(&export.stderr);
anyhow::bail!("Failed to export GPG public key: {}", stderr.trim());
}
let mut pub_file = fs::File::create(&pub_path)?;
pub_file.write_all(&export.stdout)?;
pub_file.flush()?;
println!("Public key exported to {}", pub_path.to_utf8()?);
println!();
println!("To use this key, add the following to your tasks.yaml:");
println!(" gpg_key_id: {gpg_key_id}");
Ok(())
}
}