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
parent
cd7a7272ef
commit
b945d0f142
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,24 +3,23 @@ use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use axum::async_trait;
|
use axum::async_trait;
|
||||||
|
use axum::extract::multipart::Multipart;
|
||||||
use axum::extract::FromRequestParts;
|
use axum::extract::FromRequestParts;
|
||||||
|
use axum::extract::State;
|
||||||
use axum::headers::authorization::Bearer;
|
use axum::headers::authorization::Bearer;
|
||||||
use axum::headers::{Authorization, Host};
|
use axum::headers::{Authorization, Host};
|
||||||
use axum::http::request::Parts;
|
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 axum::{RequestPartsExt, TypedHeader};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ssh_key::Algorithm;
|
use ssh_key::Algorithm;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::error::SignKeyError;
|
||||||
|
use super::{AuthError, Context};
|
||||||
use crate::auth::{self, HostClaims};
|
use crate::auth::{self, HostClaims};
|
||||||
use crate::ca;
|
use crate::ca;
|
||||||
use crate::machine_id;
|
use crate::machine_id;
|
||||||
use super::{AuthError, Context};
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct SignKeyResponse {
|
pub struct SignKeyResponse {
|
||||||
|
@ -29,67 +28,6 @@ pub struct SignKeyResponse {
|
||||||
certificates: HashMap<String, String>,
|
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]
|
#[async_trait]
|
||||||
impl FromRequestParts<Arc<Context>> for HostClaims {
|
impl FromRequestParts<Arc<Context>> for HostClaims {
|
||||||
type Rejection = AuthError;
|
type Rejection = AuthError;
|
||||||
|
@ -154,7 +92,6 @@ async fn get_machine_id(hostname: &str, ctx: &super::State) -> Option<Uuid> {
|
||||||
Some(machine_id)
|
Some(machine_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct SignKeyRequest {
|
struct SignKeyRequest {
|
||||||
hostname: String,
|
hostname: String,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod error;
|
||||||
mod host;
|
mod host;
|
||||||
mod user;
|
mod user;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue