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 pub imported_material_bytes: Option<Vec<u8>>,
69 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#[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}