diff --git a/src/client.rs b/src/client.rs index ecffe14..f6d25c0 100644 --- a/src/client.rs +++ b/src/client.rs @@ -3,6 +3,7 @@ use axum_extra::routing::TypedPath; use clap::{Args, Parser, Subcommand}; use reqwest::{Client, StatusCode}; use ssh_key::Certificate; +use std::io::{stdin, stdout}; use std::path::PathBuf; use std::time::{Duration, SystemTime}; use tokio::fs; @@ -20,6 +21,9 @@ pub struct ClientArgs { /// Url for the API endpoint #[clap(short = 'a', long = "api-endpoint", env = env_key!("API"))] api: Url, + /// Require interaction before writing certificates + #[clap(short = 'i', long = "interactive", env = env_key!("INTERACTIVE"))] + interactive: bool, } #[derive(Parser)] @@ -66,7 +70,7 @@ enum UploadError {} async fn upload( UploadArgs { - args: ClientArgs { api }, + args: ClientArgs { api, .. }, files, }: UploadArgs, ) -> anyhow::Result<()> { @@ -109,7 +113,7 @@ async fn fetch( FetchArgs { cert_dir, min_delta_days: min_delta, - args: ClientArgs { api }, + args: ClientArgs { api, interactive }, }: FetchArgs, ) -> anyhow::Result<()> { let certs = read_dir(&cert_dir).await?; @@ -133,12 +137,25 @@ async fn fetch( }); for cert in updates { if let Ok(Some((cert, update))) = cert.await? { + if interactive { + println!("certificate update: {}", cert.key_id()); + println!( + "principals: {:?}, expiry: {}", + update.valid_principals(), + update.valid_before() + ); + println!("update? : (y/n)"); + let mut yes = String::with_capacity(3); + stdin().read_line(&mut yes)?; + if !yes.starts_with(['y', 'Y']) { + break; + } + } fs::write(cert_dir.join(cert.key_id()), update.to_openssh()?).await?; + let key_id = cert.key_id(); info!( - "updated {}: {} -> {}", - cert.key_id(), - cert.serial(), - update.serial() + %key_id, + "updated certificate", ); } }