kipuka/config/cms_est.rs
1//! CMS-wrapped EST configuration (experimental CMS EST extension).
2//!
3//! The `[cms_est]` section enables EST endpoints that use CMS
4//! message-level security instead of TLS for authentication and
5//! confidentiality. This supports disconnected/air-gapped
6//! deployments where a TLS-terminating proxy handles transport.
7
8use serde::Deserialize;
9
10/// `[cms_est]` section — CMS message-level security for EST.
11///
12/// ```toml
13/// [cms_est]
14/// enabled = true
15/// require_signed_requests = true
16/// encrypt_responses = true
17/// allowed_content_encryption = ["AES-256-GCM", "AES-128-GCM"]
18/// ```
19#[derive(Debug, Clone, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct CmsEstConfig {
22 /// Enable CMS-wrapped EST endpoints.
23 #[serde(default)]
24 pub enabled: bool,
25
26 /// Require CMS SignedData wrapping on all requests.
27 #[serde(default = "default_true")]
28 pub require_signed_requests: bool,
29
30 /// Encrypt responses using CMS EnvelopedData.
31 #[serde(default = "default_true")]
32 pub encrypt_responses: bool,
33
34 /// Allowed response encryption algorithms. AES-GCM returns CMS
35 /// AuthEnvelopedData; explicitly configured AES-CBC returns EnvelopedData.
36 #[serde(default = "default_allowed_content_encryption")]
37 pub allowed_content_encryption: Vec<String>,
38}
39
40fn default_true() -> bool {
41 true
42}
43
44fn default_allowed_content_encryption() -> Vec<String> {
45 vec!["AES-256-GCM".to_string(), "AES-128-GCM".to_string()]
46}
47
48impl Default for CmsEstConfig {
49 fn default() -> Self {
50 Self {
51 enabled: false,
52 require_signed_requests: true,
53 encrypt_responses: true,
54 allowed_content_encryption: default_allowed_content_encryption(),
55 }
56 }
57}
58
59impl CmsEstConfig {
60 /// Validate CMS-EST configuration constraints.
61 pub fn validate(&self) -> Result<(), String> {
62 if self.encrypt_responses && self.allowed_content_encryption.is_empty() {
63 return Err(
64 "[cms_est].allowed_content_encryption must not be empty when encrypt_responses is true"
65 .into(),
66 );
67 }
68
69 Ok(())
70 }
71}