125 lines
3.0 KiB
Rust
125 lines
3.0 KiB
Rust
//! OCSP responder configuration.
|
|
|
|
use std::net::SocketAddr;
|
|
use std::path::PathBuf;
|
|
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct Config {
|
|
#[serde(default = "default_listen")]
|
|
pub listen: SocketAddr,
|
|
#[serde(default)]
|
|
pub s3: S3Config,
|
|
#[serde(default)]
|
|
pub issuers: Vec<IssuerConfig>,
|
|
#[serde(default = "default_ocsp_next_update_seconds")]
|
|
pub next_update_seconds: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct IssuerConfig {
|
|
pub name: String,
|
|
pub ca_id: String,
|
|
pub ca_cert: PathBuf,
|
|
pub signer_cert: PathBuf,
|
|
pub signer_key: PathBuf,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct S3Config {
|
|
pub bucket: String,
|
|
#[serde(default = "default_prefix")]
|
|
pub prefix: String,
|
|
pub region: Option<String>,
|
|
pub endpoint: Option<String>,
|
|
#[serde(default)]
|
|
pub force_path_style: bool,
|
|
#[serde(default = "default_cache_ttl_ms")]
|
|
pub cache_ttl_ms: u64,
|
|
#[serde(default = "default_stale_grace_seconds")]
|
|
pub stale_grace_seconds: u64,
|
|
}
|
|
|
|
impl Default for S3Config {
|
|
fn default() -> Self {
|
|
Self {
|
|
bucket: String::new(),
|
|
prefix: default_prefix(),
|
|
region: None,
|
|
endpoint: None,
|
|
force_path_style: false,
|
|
cache_ttl_ms: default_cache_ttl_ms(),
|
|
stale_grace_seconds: default_stale_grace_seconds(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl S3Config {
|
|
pub fn object_key(&self, ca_id: &str) -> String {
|
|
let prefix = self.prefix.trim_matches('/');
|
|
let name = format!("{}.json", ca_id.to_lowercase());
|
|
if prefix.is_empty() {
|
|
name
|
|
} else {
|
|
format!("{prefix}/{name}")
|
|
}
|
|
}
|
|
}
|
|
|
|
fn default_listen() -> SocketAddr {
|
|
"0.0.0.0:2560"
|
|
.parse()
|
|
.expect("valid default listen address")
|
|
}
|
|
|
|
fn default_prefix() -> String {
|
|
"ocsp".to_string()
|
|
}
|
|
|
|
fn default_cache_ttl_ms() -> u64 {
|
|
1000
|
|
}
|
|
|
|
fn default_stale_grace_seconds() -> u64 {
|
|
60
|
|
}
|
|
|
|
fn default_ocsp_next_update_seconds() -> u64 {
|
|
10
|
|
}
|
|
|
|
pub fn load_config() -> Result<Config, Box<dyn std::error::Error + Send + Sync>> {
|
|
let path =
|
|
std::env::var("OCSP_CONFIG").unwrap_or_else(|_| "/etc/ocsp/responder.yaml".to_string());
|
|
let text = std::fs::read_to_string(&path)?;
|
|
let mut config: Config = serde_yaml::from_str(&text)?;
|
|
if config.issuers.is_empty() {
|
|
return Err("configuration must contain at least one issuer".into());
|
|
}
|
|
if config.s3.bucket.trim().is_empty() {
|
|
return Err("s3.bucket must be configured".into());
|
|
}
|
|
if let Ok(listen) = std::env::var("OCSP_LISTEN") {
|
|
config.listen = listen.parse()?;
|
|
}
|
|
Ok(config)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn object_key_uses_ca_id() {
|
|
let config = S3Config {
|
|
prefix: "ocsp".to_string(),
|
|
..Default::default()
|
|
};
|
|
assert_eq!(
|
|
config.object_key("123E4567-E89B-12D3-A456-426614174000"),
|
|
"ocsp/123e4567-e89b-12d3-a456-426614174000.json"
|
|
);
|
|
}
|
|
}
|