use super::ApiError; use anyhow::Context; use axum::{async_trait, body::BoxBody, extract::FromRequest, http::Request}; use ssh_key::{Certificate, SshSig}; use tracing::trace; #[derive(Debug, Clone)] pub struct CertificateBody(pub Certificate); // we must implement `FromRequest` (and not `FromRequestParts`) to consume the body #[async_trait] impl FromRequest for CertificateBody where S: Send + Sync, { type Rejection = ApiError; async fn from_request(req: Request, state: &S) -> Result { let body = String::from_request(req, state) .await .context("failed to extract body")?; let cert = Certificate::from_openssh(&body) .with_context(|| format!("failed to parse '{}'", body))?; trace!(%body, "extracted certificate"); Ok(Self(cert)) } } #[derive(Debug, Clone)] pub struct SignatureBody(pub SshSig); #[async_trait] impl FromRequest for SignatureBody where S: Send + Sync, { type Rejection = ApiError; async fn from_request(req: Request, state: &S) -> Result { let body = String::from_request(req, state) .await .context("failed to extract body")?; let sig = SshSig::from_pem(&body).with_context(|| format!("failed to parse '{}'", body))?; trace!(%body, "extracted signature"); Ok(Self(sig)) } }