2022-12-24 16:57:14 +01:00

50 lines
1.4 KiB
Rust

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<S> FromRequest<S, BoxBody> for CertificateBody
where
S: Send + Sync,
{
type Rejection = ApiError;
async fn from_request(req: Request<BoxBody>, state: &S) -> Result<Self, Self::Rejection> {
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<S> FromRequest<S, BoxBody> for SignatureBody
where
S: Send + Sync,
{
type Rejection = ApiError;
async fn from_request(req: Request<BoxBody>, state: &S) -> Result<Self, Self::Rejection> {
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))
}
}