64 lines
1.9 KiB
Rust
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(())
|
|
}
|