server: Move SignKeyError to error module

The `SignKeyError` enum will also be used by the request handler for
signing SSH user certificates.  Thus, I am moving it to its own module
where it can be accessed from both places.
master
Dustin 2023-11-21 21:31:43 -06:00
parent cd7a7272ef
commit b945d0f142
3 changed files with 81 additions and 68 deletions

75
src/server/error.rs Normal file
View File

@ -0,0 +1,75 @@
//! SSHCA HTTP server errors
use axum::extract::multipart::MultipartError;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use tracing::{debug, error};
use crate::ca;
/// Error encountered while signing a key
pub enum SignKeyError {
/// Failed to parse HTTP multipart form request
Multipart(MultipartError),
/// Error handing SSH certificate
Cert(ca::CertError),
/// Error loading SSH private key file
LoadPrivateKey(ca::LoadKeyError),
/// Error parsing SSH public key
ParsePublicKey(ca::LoadKeyError),
/// Unsupported SSH key algorithm
UnsupportedAlgorithm(String),
/// No SSH public key included in request
NoKey,
}
impl From<MultipartError> for SignKeyError {
fn from(e: MultipartError) -> Self {
Self::Multipart(e)
}
}
impl From<ca::CertError> for SignKeyError {
fn from(e: ca::CertError) -> Self {
Self::Cert(e)
}
}
impl IntoResponse for SignKeyError {
fn into_response(self) -> Response {
match self {
Self::Multipart(e) => {
debug!("Error reading request: {}", e);
let body = e.to_string();
(StatusCode::BAD_REQUEST, body).into_response()
}
Self::Cert(e) => {
error!("Failed to sign certificate: {}", e);
let body = "Service Unavailable";
(StatusCode::SERVICE_UNAVAILABLE, body).into_response()
}
Self::LoadPrivateKey(e) => {
error!("Error loading CA private key: {}", e);
let body = "Service Unavailable";
(StatusCode::SERVICE_UNAVAILABLE, body).into_response()
}
Self::ParsePublicKey(e) => {
error!("Error parsing public keykey: {}", e);
let body = e.to_string();
(StatusCode::BAD_REQUEST, body).into_response()
}
Self::UnsupportedAlgorithm(a) => {
debug!("Requested certificate for unsupported key algorithm \"{}\"", a);
let body = format!("Unsupported key algorithm: {}", a);
(StatusCode::BAD_REQUEST, body).into_response()
}
Self::NoKey => {
debug!("No SSH public key provided in request");
(
StatusCode::BAD_REQUEST,
"No SSH public key provided in request",
)
.into_response()
}
}
}
}

View File

@ -3,24 +3,23 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use axum::async_trait;
use axum::extract::multipart::Multipart;
use axum::extract::FromRequestParts;
use axum::extract::State;
use axum::headers::authorization::Bearer;
use axum::headers::{Authorization, Host};
use axum::http::request::Parts;
use axum::extract::multipart::{Multipart, MultipartError};
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::{RequestPartsExt, TypedHeader};
use serde::Serialize;
use ssh_key::Algorithm;
use tracing::{debug, error, info, warn};
use tracing::{debug, info, warn};
use uuid::Uuid;
use super::error::SignKeyError;
use super::{AuthError, Context};
use crate::auth::{self, HostClaims};
use crate::ca;
use crate::machine_id;
use super::{AuthError, Context};
#[derive(Serialize)]
pub struct SignKeyResponse {
@ -29,67 +28,6 @@ pub struct SignKeyResponse {
certificates: HashMap<String, String>,
}
pub enum SignKeyError {
Multipart(MultipartError),
Cert(ca::CertError),
LoadPrivateKey(ca::LoadKeyError),
ParsePublicKey(ca::LoadKeyError),
UnsupportedAlgorithm(String),
NoKey,
}
impl From<MultipartError> for SignKeyError {
fn from(e: MultipartError) -> Self {
Self::Multipart(e)
}
}
impl From<ca::CertError> for SignKeyError {
fn from(e: ca::CertError) -> Self {
Self::Cert(e)
}
}
impl IntoResponse for SignKeyError {
fn into_response(self) -> Response {
match self {
Self::Multipart(e) => {
debug!("Error reading request: {}", e);
let body = e.to_string();
(StatusCode::BAD_REQUEST, body).into_response()
}
Self::Cert(e) => {
error!("Failed to sign certificate: {}", e);
let body = "Service Unavailable";
(StatusCode::SERVICE_UNAVAILABLE, body).into_response()
}
Self::LoadPrivateKey(e) => {
error!("Error loading CA private key: {}", e);
let body = "Service Unavailable";
(StatusCode::SERVICE_UNAVAILABLE, body).into_response()
}
Self::ParsePublicKey(e) => {
error!("Error parsing public keykey: {}", e);
let body = e.to_string();
(StatusCode::BAD_REQUEST, body).into_response()
}
Self::UnsupportedAlgorithm(a) => {
debug!("Requested certificate for unsupported key algorithm \"{}\"", a);
let body = format!("Unsupported key algorithm: {}", a);
(StatusCode::BAD_REQUEST, body).into_response()
}
Self::NoKey => {
debug!("No SSH public key provided in request");
(
StatusCode::BAD_REQUEST,
"No SSH public key provided in request",
)
.into_response()
}
}
}
}
#[async_trait]
impl FromRequestParts<Arc<Context>> for HostClaims {
type Rejection = AuthError;
@ -154,7 +92,6 @@ async fn get_machine_id(hostname: &str, ctx: &super::State) -> Option<Uuid> {
Some(machine_id)
}
#[derive(Default)]
struct SignKeyRequest {
hostname: String,

View File

@ -1,3 +1,4 @@
mod error;
mod host;
mod user;