Skip to main content

fakecloud_kms/
state.rs

1use std::collections::HashMap;
2use std::sync::Arc;
3
4use parking_lot::RwLock;
5
6pub type SharedKmsState = Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<KmsState>>>;
7
8impl fakecloud_core::multi_account::AccountState for KmsState {
9    fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
10        Self::new(account_id, region)
11    }
12}
13
14#[derive(Clone, serde::Serialize, serde::Deserialize)]
15pub struct KmsState {
16    pub account_id: String,
17    pub region: String,
18    pub keys: HashMap<String, KmsKey>,
19    pub aliases: HashMap<String, KmsAlias>,
20    pub grants: Vec<KmsGrant>,
21    pub custom_key_stores: HashMap<String, CustomKeyStore>,
22}
23
24impl KmsState {
25    pub fn new(account_id: &str, region: &str) -> Self {
26        Self {
27            account_id: account_id.to_string(),
28            region: region.to_string(),
29            keys: HashMap::new(),
30            aliases: HashMap::new(),
31            grants: Vec::new(),
32            custom_key_stores: HashMap::new(),
33        }
34    }
35
36    pub fn reset(&mut self) {
37        self.keys.clear();
38        self.aliases.clear();
39        self.grants.clear();
40        self.custom_key_stores.clear();
41    }
42}
43
44#[derive(Clone, serde::Serialize, serde::Deserialize)]
45pub struct KmsKey {
46    pub key_id: String,
47    pub arn: String,
48    pub creation_date: f64,
49    pub description: String,
50    pub enabled: bool,
51    pub key_usage: String,
52    pub key_spec: String,
53    pub key_manager: String,
54    pub key_state: String,
55    pub deletion_date: Option<f64>,
56    pub tags: HashMap<String, String>,
57    pub policy: String,
58    pub key_rotation_enabled: bool,
59    pub origin: String,
60    pub multi_region: bool,
61    pub rotations: Vec<KeyRotation>,
62    pub signing_algorithms: Option<Vec<String>>,
63    pub encryption_algorithms: Option<Vec<String>>,
64    pub mac_algorithms: Option<Vec<String>>,
65    pub custom_key_store_id: Option<String>,
66    pub imported_key_material: bool,
67    /// Raw bytes of imported key material (used as AES key for encrypt/decrypt).
68    pub imported_material_bytes: Option<Vec<u8>>,
69    /// Deterministic seed for the key (used for DeriveSharedSecret).
70    pub private_key_seed: Vec<u8>,
71    pub primary_region: Option<String>,
72}
73
74#[derive(Clone, serde::Serialize, serde::Deserialize)]
75pub struct KmsAlias {
76    pub alias_name: String,
77    pub alias_arn: String,
78    pub target_key_id: String,
79    pub creation_date: f64,
80}
81
82#[derive(Clone, serde::Serialize, serde::Deserialize)]
83pub struct KmsGrant {
84    pub grant_id: String,
85    pub grant_token: String,
86    pub key_id: String,
87    pub grantee_principal: String,
88    pub retiring_principal: Option<String>,
89    pub operations: Vec<String>,
90    pub constraints: Option<serde_json::Value>,
91    pub name: Option<String>,
92    pub creation_date: f64,
93}
94
95#[derive(Clone, serde::Serialize, serde::Deserialize)]
96pub struct KeyRotation {
97    pub key_id: String,
98    pub rotation_date: f64,
99    pub rotation_type: String,
100}
101
102#[derive(Clone, serde::Serialize, serde::Deserialize)]
103pub struct CustomKeyStore {
104    pub custom_key_store_id: String,
105    pub custom_key_store_name: String,
106    pub custom_key_store_type: String,
107    pub cloud_hsm_cluster_id: Option<String>,
108    pub trust_anchor_certificate: Option<String>,
109    pub connection_state: String,
110    pub creation_date: f64,
111    pub xks_proxy_uri_endpoint: Option<String>,
112    pub xks_proxy_uri_path: Option<String>,
113    pub xks_proxy_vpc_endpoint_service_name: Option<String>,
114    pub xks_proxy_connectivity: Option<String>,
115}
116
117/// On-disk snapshot envelope for KMS state. Versioned so format
118/// changes fail loudly on upgrade.
119#[derive(Clone, serde::Serialize, serde::Deserialize)]
120pub struct KmsSnapshot {
121    pub schema_version: u32,
122    #[serde(default)]
123    pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<KmsState>>,
124    #[serde(default)]
125    pub state: Option<KmsState>,
126}
127
128pub const KMS_SNAPSHOT_SCHEMA_VERSION: u32 = 2;
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[test]
135    fn new_has_empty_collections() {
136        let state = KmsState::new("123456789012", "us-east-1");
137        assert_eq!(state.account_id, "123456789012");
138        assert_eq!(state.region, "us-east-1");
139        assert!(state.keys.is_empty());
140        assert!(state.aliases.is_empty());
141        assert!(state.grants.is_empty());
142        assert!(state.custom_key_stores.is_empty());
143    }
144
145    #[test]
146    fn reset_clears_collections() {
147        let mut state = KmsState::new("123456789012", "us-east-1");
148        state.aliases.insert(
149            "alias/test".to_string(),
150            KmsAlias {
151                alias_name: "alias/test".to_string(),
152                alias_arn: "arn".to_string(),
153                target_key_id: "k".to_string(),
154                creation_date: 0.0,
155            },
156        );
157        assert!(!state.aliases.is_empty());
158        state.reset();
159        assert!(state.aliases.is_empty());
160    }
161}