fakecloud_secretsmanager/
state.rs1use chrono::{DateTime, Utc};
2use parking_lot::RwLock;
3use std::collections::BTreeMap;
4use std::sync::Arc;
5
6#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
7pub struct Secret {
8 pub name: String,
9 pub arn: String,
10 pub description: Option<String>,
11 pub kms_key_id: Option<String>,
12 pub versions: BTreeMap<String, SecretVersion>,
13 pub current_version_id: Option<String>,
14 pub tags: Vec<(String, String)>,
15 pub tags_ever_set: bool,
16 pub deleted: bool,
17 pub deletion_date: Option<DateTime<Utc>>,
18 pub created_at: DateTime<Utc>,
19 pub last_changed_at: DateTime<Utc>,
20 pub last_accessed_at: Option<DateTime<Utc>>,
21 pub rotation_enabled: Option<bool>,
22 pub rotation_lambda_arn: Option<String>,
23 pub rotation_rules: Option<RotationRules>,
24 pub last_rotated_at: Option<DateTime<Utc>>,
25 pub resource_policy: Option<String>,
26 #[serde(default)]
29 pub replica_regions: Vec<String>,
30}
31
32#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
33pub struct RotationRules {
34 pub automatically_after_days: Option<i64>,
35 #[serde(default, skip_serializing_if = "Option::is_none")]
38 pub duration: Option<String>,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub schedule_expression: Option<String>,
42}
43
44#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
45pub struct SecretVersion {
46 pub version_id: String,
47 pub secret_string: Option<String>,
48 pub secret_binary: Option<Vec<u8>>,
49 pub stages: Vec<String>,
50 pub created_at: DateTime<Utc>,
51}
52
53#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
54pub struct SecretsManagerState {
55 pub account_id: String,
56 pub region: String,
57 pub secrets: BTreeMap<String, Secret>,
58}
59
60impl SecretsManagerState {
61 pub fn new(account_id: &str, region: &str) -> Self {
62 Self {
63 account_id: account_id.to_string(),
64 region: region.to_string(),
65 secrets: BTreeMap::new(),
66 }
67 }
68
69 pub fn reset(&mut self) {
70 self.secrets.clear();
71 }
72}
73
74pub type SharedSecretsManagerState =
75 Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<SecretsManagerState>>>;
76
77impl fakecloud_core::multi_account::AccountState for SecretsManagerState {
78 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
79 Self::new(account_id, region)
80 }
81}
82
83#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
86pub struct SecretsManagerSnapshot {
87 pub schema_version: u32,
88 #[serde(default)]
89 pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<SecretsManagerState>>,
90 #[serde(default)]
91 pub state: Option<SecretsManagerState>,
92}
93
94pub const SECRETSMANAGER_SNAPSHOT_SCHEMA_VERSION: u32 = 2;
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn new_initializes_empty() {
102 let state = SecretsManagerState::new("123456789012", "us-east-1");
103 assert_eq!(state.account_id, "123456789012");
104 assert_eq!(state.region, "us-east-1");
105 assert!(state.secrets.is_empty());
106 }
107
108 #[test]
109 fn reset_clears_secrets() {
110 let mut state = SecretsManagerState::new("123456789012", "us-east-1");
111 state.secrets.insert(
112 "s1".to_string(),
113 Secret {
114 name: "s1".to_string(),
115 arn: "arn".to_string(),
116 description: None,
117 kms_key_id: None,
118 versions: BTreeMap::new(),
119 current_version_id: None,
120 tags: vec![],
121 tags_ever_set: false,
122 deleted: false,
123 deletion_date: None,
124 created_at: Utc::now(),
125 last_changed_at: Utc::now(),
126 last_accessed_at: None,
127 rotation_enabled: None,
128 rotation_lambda_arn: None,
129 rotation_rules: None,
130 last_rotated_at: None,
131 resource_policy: None,
132 replica_regions: Vec::new(),
133 },
134 );
135 state.reset();
136 assert!(state.secrets.is_empty());
137 }
138}