use image4_pki::DigestAlgo;
use serde::{Deserialize, Serialize};
use std::{net::SocketAddr, path::PathBuf};
mod digest_serde {
use super::*;
use serde::{
de::{Unexpected, Visitor},
Deserializer, Serializer,
};
struct DigestAlgoWrapper(DigestAlgo);
impl Serialize for DigestAlgoWrapper {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_some(match self.0 {
DigestAlgo::Sha1 => "sha1",
DigestAlgo::Sha256 => "sha256",
DigestAlgo::Sha384 => "sha384",
_ => panic!("unhandled digest algorithm"),
})
}
}
struct DigestAlgoVisitor;
impl Visitor<'_> for DigestAlgoVisitor {
type Value = DigestAlgo;
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match v {
"sha1" => Ok(DigestAlgo::Sha1),
"sha256" => Ok(DigestAlgo::Sha256),
"sha384" => Ok(DigestAlgo::Sha384),
other => Err(E::invalid_value(Unexpected::Str(other), &self)),
}
}
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("\"sha1\", \"sha256\" or \"sha384\"")
}
}
impl<'de> Deserialize<'de> for DigestAlgoWrapper {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer
.deserialize_str(DigestAlgoVisitor)
.map(DigestAlgoWrapper)
}
}
pub(super) fn serialize<S: Serializer>(
algo: &Option<DigestAlgo>,
serializer: S,
) -> Result<S::Ok, S::Error> {
(*algo).map(DigestAlgoWrapper).serialize(serializer)
}
pub(super) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Option<DigestAlgo>, D::Error> {
let deserialized = Option::<DigestAlgoWrapper>::deserialize(deserializer)?;
Ok(deserialized.map(|wrapper| wrapper.0))
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SignerConfig {
pub certificate_chain_path: PathBuf,
pub private_key_path: PathBuf,
#[serde(with = "digest_serde", default)]
pub digest_algorithm: Option<DigestAlgo>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SignersConfig {
pub ap_ticket_signer: SignerConfig,
pub local_policy_signer: SignerConfig,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SetupConfig {
pub listen_addr: SocketAddr,
#[serde(flatten)]
pub signers: SignersConfig,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimeConfig {
#[serde(default)]
pub forward_local_policy: bool,
#[serde(default)]
pub user_agent: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Config {
#[serde(flatten)]
pub setup: SetupConfig,
#[serde(flatten)]
pub runtime: RuntimeConfig,
}