sshca-cli/src/user/cert.rs

64 lines
1.9 KiB
Rust

use std::path::Path;
use reqwest::multipart::{Form, Part};
use reqwest::{StatusCode, Url};
use tracing::{debug, error, info};
pub async fn sign_key(token: &str) -> Result<(), Box<dyn std::error::Error>> {
let url = crate::get_sshca_server_url()?;
let pubkey = Path::new("/home/dustin/.ssh/id_ed25519.pub");
let pubkey_path = pubkey.to_owned();
let pubkey = std::fs::read_to_string(&pubkey_path)?;
let mut url =
Url::parse(&url).map_err(|e| format!("Invalid URL: {}", e))?;
url.path_segments_mut()
.map_err(|_| "Invalid URL: missing host")?
.pop_if_empty()
.push("user")
.push("sign");
let form = Form::new().part(
"pubkey",
Part::bytes(pubkey.into_bytes()).file_name(
pubkey_path
.file_name()
.ok_or("Invalid public key file path")?
.to_str()
.ok_or("Invalid public key file path")?
.to_string(),
),
);
let client = reqwest::Client::new();
info!(
"Requesting SSH user certificate for {} with key {}",
"-",
pubkey_path.display()
);
debug!("Request: POST {}", url);
let res = client
.post(url)
.header("Authorization", format!("Bearer {}", token))
.multipart(form)
.send()
.await?;
debug!("Response: {:?} {}", &res.version(), &res.status());
match res.error_for_status_ref() {
Ok(_) => (),
Err(e) if e.status() == Some(StatusCode::BAD_REQUEST) => {
let msg = res.text().await.unwrap_or_else(|e| e.to_string());
error!("{}: {}", e, msg);
return Err(format!("{}\n{}", e, msg).into());
}
Err(e) => {
error!("{}", e);
return Err(e.into());
}
};
let cert = res.text().await?;
println!("{}", cert);
Ok(())
}