Add S3 OCSP status publishing and standalone Rust Axum responder

This commit is contained in:
woggioni committed 2026-10-23 09:18:00 +00:00
1 parent 4ed14b42a7
commit 0384995570
30 files changed
+5274 -5

No files matched your search

+91
View File
@@ -0,0 +1,91 @@
//! Standalone KCA OCSP responder.
mod cache;
mod config;
mod issuer;
mod ocsp;
mod signer;
mod snapshot;
mod store;
use std::sync::Arc;
use axum::extract::DefaultBodyLimit;
use axum::routing::{get, post};
use axum::Router;
use tower_http::timeout::TimeoutLayer;
use tracing_subscriber::EnvFilter;
use crate::issuer::Issuer;
use crate::ocsp::AppState;
use crate::store::StatusStore;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if std::env::args().any(|argument| argument == "--healthcheck") {
return healthcheck();
}
tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
)
.init();
let config = config::load_config()?;
let store = StatusStore::new(&config.s3).await;
let mut issuers = Vec::with_capacity(config.issuers.len());
for issuer_config in &config.issuers {
let issuer = Issuer::load(issuer_config)?;
tracing::info!(
issuer = %issuer.name,
fingerprint = %issuer.fingerprint,
"loaded OCSP issuer"
);
issuers.push(issuer);
}
let state = AppState {
issuers,
store,
config: Arc::new(config.clone()),
};
let app = Router::new()
.route("/ocsp", post(ocsp::ocsp_post))
.route("/ocsp/{request}", get(ocsp::ocsp_get))
.route("/healthz", get(health))
.route("/readyz", get(health))
.layer(DefaultBodyLimit::max(16 * 1024))
.layer(TimeoutLayer::with_status_code(
axum::http::StatusCode::REQUEST_TIMEOUT,
std::time::Duration::from_secs(15),
))
.with_state(state);
let listener = tokio::net::TcpListener::bind(config.listen).await?;
tracing::info!(listen = %config.listen, "OCSP responder listening");
axum::serve(listener, app)
.with_graceful_shutdown(shutdown_signal())
.await?;
Ok(())
}
async fn health() -> &'static str {
"ok"
}
fn healthcheck() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
use std::io::{Read, Write};
let mut stream = std::net::TcpStream::connect("127.0.0.1:2560")?;
stream.write_all(b"GET /healthz HTTP/1.0\r\nHost: localhost\r\n\r\n")?;
let mut response = String::new();
stream.read_to_string(&mut response)?;
if response.starts_with("HTTP/1.") && response.contains(" 200 ") {
Ok(())
} else {
Err("health endpoint did not return HTTP 200".into())
}
}
async fn shutdown_signal() {
let _ = tokio::signal::ctrl_c().await;
}