Add S3 OCSP status publishing and standalone Rust Axum responder
This commit is contained in:
1 parent
4ed14b42a7
commit
0384995570
30 files changed
+5274
-5
No files matched your search
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user