photoncloud-monorepo/deployer/crates/deployer-server/src/auth.rs

101 lines
2.8 KiB
Rust

use axum::http::{HeaderMap, StatusCode};
use tracing::warn;
use crate::state::AppState;
pub fn require_bootstrap_auth(
state: &AppState,
headers: &HeaderMap,
) -> Result<(), (StatusCode, String)> {
if state.config.allow_unauthenticated {
return Ok(());
}
let expected = match state.config.bootstrap_token.as_deref() {
Some(token) if !token.is_empty() => token,
_ => {
return Err((
StatusCode::SERVICE_UNAVAILABLE,
"bootstrap token not configured".to_string(),
))
}
};
let provided = extract_token(headers);
if provided.as_deref() == Some(expected) {
return Ok(());
}
Err((
StatusCode::UNAUTHORIZED,
"invalid bootstrap token".to_string(),
))
}
pub fn require_admin_auth(
state: &AppState,
headers: &HeaderMap,
) -> Result<(), (StatusCode, String)> {
if state.config.allow_unauthenticated {
return Ok(());
}
let expected = match state.config.admin_token.as_deref() {
Some(token) if !token.is_empty() => token,
_ => {
if !state.config.allow_admin_fallback {
return Err((
StatusCode::SERVICE_UNAVAILABLE,
"admin token not configured".to_string(),
));
}
match state.config.bootstrap_token.as_deref() {
Some(token) if !token.is_empty() => {
warn!("admin token not configured; falling back to bootstrap token");
token
}
_ => {
return Err((
StatusCode::SERVICE_UNAVAILABLE,
"admin token not configured".to_string(),
))
}
}
}
};
let provided = extract_token(headers);
if provided.as_deref() == Some(expected) {
return Ok(());
}
Err((StatusCode::UNAUTHORIZED, "invalid admin token".to_string()))
}
fn extract_token(headers: &HeaderMap) -> Option<String> {
if let Some(value) = headers.get("x-deployer-token") {
if let Ok(token) = value.to_str() {
let trimmed = token.trim();
if !trimmed.is_empty() {
return Some(trimmed.to_string());
}
}
}
if let Some(value) = headers.get("authorization") {
if let Ok(auth) = value.to_str() {
let trimmed = auth.trim();
if let Some((scheme, rest)) = trimmed.split_once(' ') {
if scheme.eq_ignore_ascii_case("bearer") {
let token = rest.trim();
if !token.is_empty() {
return Some(token.to_string());
}
}
}
}
}
None
}