Skip to main content

rustack_cloudfront_core/
config.rs

1//! Runtime configuration for the CloudFront service.
2//!
3//! All configuration is env-driven to match the pattern used by other Rustack
4//! services; no hot-reload.
5
6use std::time::Duration;
7
8/// Config for the CloudFront management plane.
9#[derive(Debug, Clone)]
10pub struct CloudFrontConfig {
11    /// Whether to skip SigV4 signature validation on incoming requests.
12    pub skip_signature_validation: bool,
13    /// Region to report in ARNs (CloudFront is global but the SDK still signs
14    /// with a region — we accept any).
15    pub default_region: String,
16    /// 12-digit account ID used in ARNs.
17    pub account_id: String,
18    /// Host suffix emitted in distribution `DomainName` fields.
19    ///
20    /// Defaults to `cloudfront.net`. Override with `CLOUDFRONT_DOMAIN_SUFFIX`.
21    pub domain_suffix: String,
22    /// Simulated propagation delay for `CreateDistribution` / `UpdateDistribution`
23    /// (`InProgress` → `Deployed`).
24    pub distribution_propagation: Duration,
25    /// Simulated propagation delay for invalidations (`InProgress` → `Completed`).
26    pub invalidation_propagation: Duration,
27    /// Whether resource IDs are derived from a hash of their input rather than
28    /// random. Useful for snapshot tests.
29    pub deterministic_ids: bool,
30}
31
32impl Default for CloudFrontConfig {
33    fn default() -> Self {
34        Self {
35            skip_signature_validation: true,
36            default_region: "us-east-1".to_owned(),
37            account_id: "000000000000".to_owned(),
38            domain_suffix: "cloudfront.net".to_owned(),
39            distribution_propagation: Duration::from_millis(0),
40            invalidation_propagation: Duration::from_millis(0),
41            deterministic_ids: false,
42        }
43    }
44}
45
46impl CloudFrontConfig {
47    /// Load config from environment variables, falling back to defaults.
48    #[must_use]
49    pub fn from_env() -> Self {
50        let mut cfg = Self::default();
51
52        if let Ok(v) = std::env::var("CLOUDFRONT_SKIP_SIGNATURE_VALIDATION") {
53            cfg.skip_signature_validation = parse_bool(&v).unwrap_or(cfg.skip_signature_validation);
54        }
55        if let Ok(v) = std::env::var("AWS_DEFAULT_REGION") {
56            cfg.default_region = v;
57        }
58        if let Ok(v) =
59            std::env::var("ACCOUNT_ID").or_else(|_| std::env::var("CLOUDFRONT_ACCOUNT_ID"))
60        {
61            cfg.account_id = v;
62        }
63        if let Ok(v) = std::env::var("CLOUDFRONT_DOMAIN_SUFFIX") {
64            cfg.domain_suffix = v;
65        }
66        if let Ok(v) = std::env::var("CLOUDFRONT_DISTRIBUTION_PROPAGATION_MS") {
67            if let Ok(ms) = v.parse::<u64>() {
68                cfg.distribution_propagation = Duration::from_millis(ms);
69            }
70        }
71        if let Ok(v) = std::env::var("CLOUDFRONT_INVALIDATION_PROPAGATION_MS") {
72            if let Ok(ms) = v.parse::<u64>() {
73                cfg.invalidation_propagation = Duration::from_millis(ms);
74            }
75        }
76        if let Ok(v) = std::env::var("CLOUDFRONT_DETERMINISTIC_IDS") {
77            cfg.deterministic_ids = parse_bool(&v).unwrap_or(false);
78        }
79
80        cfg
81    }
82}
83
84fn parse_bool(s: &str) -> Option<bool> {
85    match s.trim().to_ascii_lowercase().as_str() {
86        "1" | "true" | "yes" | "on" => Some(true),
87        "0" | "false" | "no" | "off" => Some(false),
88        _ => None,
89    }
90}