1use std::collections::HashMap;
2
3use chrono::Utc;
4
5use crate::types::*;
6
7#[derive(Debug, Default)]
8pub struct SecretsManagerState {
9 pub secrets: HashMap<String, Secret>,
10}
11
12#[derive(Debug, thiserror::Error)]
13pub enum SecretsManagerError {
14 #[error("A resource with the ID you requested already exists.")]
15 ResourceExists,
16 #[error("You tried to perform the operation on a secret that's currently marked deleted.")]
17 SecretMarkedDeleted,
18 #[error("Secrets Manager can't find the specified secret value for VersionId: {version_id}")]
19 SecretVersionNotFoundById { version_id: String },
20 #[error("Secrets Manager can't find the specified secret value for staging label: {stage}")]
21 SecretVersionNotFoundByStage { stage: String },
22 #[error(
23 "An error occurred (InvalidParameterException) when calling the DeleteSecret operation: RecoveryWindowInDays value must be between 7 and 30 days (inclusive)."
24 )]
25 InvalidRecoveryWindow,
26 #[error(
27 "An error occurred (InvalidParameterException) when calling the DeleteSecret operation: You can't use ForceDeleteWithoutRecovery in conjunction with RecoveryWindowInDays."
28 )]
29 ForceDeleteWithRecoveryWindow,
30 #[error("Secrets Manager can't find the specified secret.")]
31 SecretNotFound,
32 #[error("ClientError")]
33 PasswordTooShort,
34 #[error("InvalidParameterValue")]
35 PasswordTooLong,
36 #[error("InvalidParameterException")]
37 NoValidCharsForPassword,
38 #[error("RotationRules.AutomaticallyAfterDays must be within 1-1000.")]
39 InvalidRotationDays,
40 #[error(
41 "The parameter RemoveFromVersionId can't be empty. Staging label AWSCURRENT is currently attached to version {vid}, so you must explicitly reference that version in RemoveFromVersionId."
42 )]
43 MissingRemoveFromVersionId { vid: String },
44 #[error("Not a valid version: {version_id}")]
45 NotAValidVersion { version_id: String },
46}
47
48impl SecretsManagerState {
49 pub fn create_secret(
50 &mut self,
51 name: &str,
52 description: &str,
53 secret_string: Option<&str>,
54 secret_binary: Option<Vec<u8>>,
55 account_id: &str,
56 region: &str,
57 tags: HashMap<String, String>,
58 ) -> Result<&Secret, SecretsManagerError> {
59 if self.secrets.contains_key(name) {
60 return Err(SecretsManagerError::ResourceExists);
61 }
62
63 let arn = format!(
64 "arn:aws:secretsmanager:{region}:{account_id}:secret:{name}-{suffix}",
65 suffix = &uuid::Uuid::new_v4().to_string()[..6]
66 );
67 let now = Utc::now();
68
69 let has_value = secret_string.is_some() || secret_binary.is_some();
70
71 let mut versions = HashMap::new();
72 let current_version_id = if has_value {
73 let version_id = uuid::Uuid::new_v4().to_string();
74 let version = SecretVersion {
75 version_id: version_id.clone(),
76 secret_string: secret_string.map(|s| s.to_string()),
77 secret_binary,
78 created_date: now,
79 version_stages: vec!["AWSCURRENT".to_string()],
80 };
81 versions.insert(version_id.clone(), version);
82 Some(version_id)
83 } else {
84 None
85 };
86
87 let secret = Secret {
88 name: name.to_string(),
89 arn,
90 description: description.to_string(),
91 created_date: now,
92 last_changed_date: now,
93 versions,
94 current_version_id,
95 deleted_date: None,
96 tags,
97 resource_policy: None,
98 rotation_enabled: None,
99 rotation_lambda_arn: None,
100 rotation_rules: None,
101 last_rotated_date: None,
102 replication_status: Vec::new(),
103 primary_region: Some(region.to_string()),
104 };
105
106 self.secrets.insert(name.to_string(), secret);
107 Ok(self.secrets.get(name).unwrap())
108 }
109
110 pub fn get_secret_value(
111 &self,
112 secret_id: &str,
113 ) -> Result<(&Secret, &SecretVersion), SecretsManagerError> {
114 self.get_secret_value_by_stage(secret_id, None)
115 }
116
117 pub fn get_secret_value_by_version_id(
118 &self,
119 secret_id: &str,
120 version_id: &str,
121 ) -> Result<(&Secret, &SecretVersion), SecretsManagerError> {
122 let secret = self.find_secret(secret_id)?;
123
124 if secret.deleted_date.is_some() {
125 return Err(SecretsManagerError::SecretMarkedDeleted);
126 }
127
128 match secret.versions.get(version_id) {
129 Some(version) => Ok((secret, version)),
130 None => Err(SecretsManagerError::SecretVersionNotFoundById {
131 version_id: version_id.to_string(),
132 }),
133 }
134 }
135
136 pub fn get_secret_value_by_stage(
137 &self,
138 secret_id: &str,
139 version_stage: Option<&str>,
140 ) -> Result<(&Secret, &SecretVersion), SecretsManagerError> {
141 let secret = self.find_secret(secret_id)?;
142 let stage = version_stage.unwrap_or("AWSCURRENT");
143
144 if secret.deleted_date.is_some() {
145 return Err(SecretsManagerError::SecretMarkedDeleted);
146 }
147
148 for version in secret.versions.values() {
150 if version.version_stages.contains(&stage.to_string()) {
151 return Ok((secret, version));
152 }
153 }
154
155 Err(SecretsManagerError::SecretVersionNotFoundByStage {
156 stage: stage.to_string(),
157 })
158 }
159
160 pub fn put_secret_value(
161 &mut self,
162 secret_id: &str,
163 secret_string: Option<&str>,
164 secret_binary: Option<Vec<u8>>,
165 ) -> Result<(&Secret, String), SecretsManagerError> {
166 match self.put_secret_value_ext(secret_id, secret_string, secret_binary, None, None) {
167 Ok((secret, version_id, _stages)) => Ok((secret, version_id)),
168 Err(e) => Err(e),
169 }
170 }
171
172 pub fn put_secret_value_ext(
173 &mut self,
174 secret_id: &str,
175 secret_string: Option<&str>,
176 secret_binary: Option<Vec<u8>>,
177 client_request_token: Option<&str>,
178 version_stages: Option<&[String]>,
179 ) -> Result<(&Secret, String, Vec<String>), SecretsManagerError> {
180 let secret = self.find_secret_mut(secret_id)?;
181
182 if secret.deleted_date.is_some() {
183 return Err(SecretsManagerError::SecretMarkedDeleted);
184 }
185
186 let now = Utc::now();
187 let new_version_id = client_request_token
188 .map(|s| s.to_string())
189 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
190
191 let stages = version_stages
192 .map(|s| s.to_vec())
193 .unwrap_or_else(|| vec!["AWSCURRENT".to_string()]);
194
195 let is_current = stages.contains(&"AWSCURRENT".to_string());
196
197 if is_current {
198 if let Some(old_vid) = &secret.current_version_id
200 && let Some(old_version) = secret.versions.get_mut(old_vid)
201 {
202 old_version.version_stages.retain(|s| s != "AWSCURRENT");
203 if !old_version
204 .version_stages
205 .contains(&"AWSPREVIOUS".to_string())
206 {
207 old_version.version_stages.push("AWSPREVIOUS".to_string());
208 }
209 }
210 }
211
212 for stage in &stages {
214 if stage != "AWSCURRENT" {
215 for existing_version in secret.versions.values_mut() {
216 existing_version.version_stages.retain(|s| s != stage);
217 }
218 }
219 }
220
221 let version = SecretVersion {
222 version_id: new_version_id.clone(),
223 secret_string: secret_string.map(|s| s.to_string()),
224 secret_binary,
225 created_date: now,
226 version_stages: stages.clone(),
227 };
228
229 secret.versions.insert(new_version_id.clone(), version);
230 if is_current {
231 secret.current_version_id = Some(new_version_id.clone());
232 }
233 secret.last_changed_date = now;
234
235 secret.versions.retain(|_k, v| !v.version_stages.is_empty());
237
238 let name = secret.name.clone();
239 Ok((self.secrets.get(&name).unwrap(), new_version_id, stages))
240 }
241
242 pub fn delete_secret(
243 &mut self,
244 secret_id: &str,
245 recovery_window_in_days: Option<i64>,
246 force_delete: bool,
247 account_id: &str,
248 region: &str,
249 ) -> Result<Secret, SecretsManagerError> {
250 if let Some(days) = recovery_window_in_days
252 && !(7..=30).contains(&days)
253 {
254 return Err(SecretsManagerError::InvalidRecoveryWindow);
255 }
256
257 if force_delete && recovery_window_in_days.is_some() {
259 return Err(SecretsManagerError::ForceDeleteWithRecoveryWindow);
260 }
261
262 if force_delete {
263 match self.resolve_name(secret_id) {
265 Ok(name) => {
266 let _secret = self.find_secret_mut_raw(&name)?;
267 let mut secret = self.secrets.remove(&name).unwrap();
269 secret.deleted_date = Some(Utc::now());
270 return Ok(secret);
271 }
272 Err(_) => {
273 return Ok(Secret {
275 name: secret_id.to_string(),
276 arn: format!(
277 "arn:aws:secretsmanager:{region}:{account_id}:secret:{secret_id}"
278 ),
279 description: String::new(),
280 created_date: Utc::now(),
281 last_changed_date: Utc::now(),
282 versions: HashMap::new(),
283 current_version_id: None,
284 deleted_date: Some(Utc::now()),
285 tags: HashMap::new(),
286 resource_policy: None,
287 rotation_enabled: None,
288 rotation_lambda_arn: None,
289 rotation_rules: None,
290 last_rotated_date: None,
291 replication_status: Vec::new(),
292 primary_region: None,
293 });
294 }
295 }
296 }
297
298 let secret = self.find_secret_mut(secret_id)?;
299
300 if secret.deleted_date.is_some() {
301 return Err(SecretsManagerError::SecretMarkedDeleted);
302 }
303
304 let _window = recovery_window_in_days.unwrap_or(30);
305 secret.deleted_date = Some(Utc::now());
306
307 Ok(secret.clone())
308 }
309
310 fn find_secret_mut_raw(&mut self, name: &str) -> Result<&mut Secret, SecretsManagerError> {
311 self.secrets
312 .get_mut(name)
313 .ok_or(SecretsManagerError::SecretNotFound)
314 }
315
316 pub fn restore_secret(&mut self, secret_id: &str) -> Result<&Secret, SecretsManagerError> {
317 let secret = self.find_secret_mut(secret_id)?;
318 secret.deleted_date = None;
320 let name = secret.name.clone();
321 Ok(self.secrets.get(&name).unwrap())
322 }
323
324 pub fn describe_secret(&self, secret_id: &str) -> Result<&Secret, SecretsManagerError> {
325 self.find_secret(secret_id)
326 }
327
328 pub fn list_secrets(&self) -> Vec<&Secret> {
329 self.secrets
330 .values()
331 .filter(|s| s.deleted_date.is_none())
332 .collect()
333 }
334
335 pub fn update_secret(
336 &mut self,
337 secret_id: &str,
338 description: Option<&str>,
339 secret_string: Option<&str>,
340 secret_binary: Option<Vec<u8>>,
341 ) -> Result<&Secret, SecretsManagerError> {
342 let secret = self.find_secret_mut(secret_id)?;
343
344 if let Some(desc) = description {
345 secret.description = desc.to_string();
346 }
347
348 if secret_string.is_some() || secret_binary.is_some() {
349 let now = Utc::now();
350 let new_version_id = uuid::Uuid::new_v4().to_string();
351
352 if let Some(old_vid) = &secret.current_version_id
353 && let Some(old_version) = secret.versions.get_mut(old_vid)
354 {
355 old_version.version_stages.retain(|s| s != "AWSCURRENT");
356 if !old_version
357 .version_stages
358 .contains(&"AWSPREVIOUS".to_string())
359 {
360 old_version.version_stages.push("AWSPREVIOUS".to_string());
361 }
362 }
363
364 let version = SecretVersion {
365 version_id: new_version_id.clone(),
366 secret_string: secret_string.map(|s| s.to_string()),
367 secret_binary,
368 created_date: now,
369 version_stages: vec!["AWSCURRENT".to_string()],
370 };
371
372 secret.versions.insert(new_version_id.clone(), version);
373 secret.current_version_id = Some(new_version_id);
374 secret.last_changed_date = now;
375 }
376
377 let name = secret.name.clone();
378 Ok(self.secrets.get(&name).unwrap())
379 }
380
381 pub fn batch_get_secret_value(
382 &self,
383 secret_ids: &[String],
384 ) -> Result<Vec<(&Secret, &SecretVersion)>, Vec<(String, SecretsManagerError)>> {
385 let mut values = Vec::new();
386 let mut errors = Vec::new();
387
388 for secret_id in secret_ids {
389 match self.get_secret_value(secret_id) {
390 Ok(pair) => values.push(pair),
391 Err(e) => errors.push((secret_id.clone(), e)),
392 }
393 }
394
395 if values.is_empty() && !errors.is_empty() {
396 Err(errors)
397 } else {
398 Ok(values)
399 }
400 }
401
402 pub fn cancel_rotate_secret(
403 &mut self,
404 secret_id: &str,
405 ) -> Result<&Secret, SecretsManagerError> {
406 let secret = self.find_secret_mut(secret_id)?;
407 let name = secret.name.clone();
409 Ok(self.secrets.get(&name).unwrap())
410 }
411
412 pub fn get_random_password(
413 &self,
414 password_length: Option<i64>,
415 exclude_characters: Option<&str>,
416 exclude_numbers: bool,
417 exclude_punctuation: bool,
418 exclude_uppercase: bool,
419 exclude_lowercase: bool,
420 include_space: bool,
421 require_each_included_type: bool,
422 ) -> Result<String, SecretsManagerError> {
423 let length = password_length.unwrap_or(32) as usize;
424 if length < 4 {
425 return Err(SecretsManagerError::PasswordTooShort);
426 }
427 if length > 4096 {
428 return Err(SecretsManagerError::PasswordTooLong);
429 }
430
431 let exclude_chars = exclude_characters.unwrap_or("");
432
433 let lowercase = "abcdefghijklmnopqrstuvwxyz";
434 let uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
435 let digits = "0123456789";
436 let punctuation = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
437
438 let mut chars = String::new();
439 let mut required_chars: Vec<char> = Vec::new();
440
441 if include_space {
443 chars.push(' ');
444 required_chars.push(' ');
445 }
446 if !exclude_lowercase {
447 chars.push_str(lowercase);
448 let filtered: Vec<char> = lowercase
449 .chars()
450 .filter(|c| !exclude_chars.contains(*c))
451 .collect();
452 if !filtered.is_empty() {
453 let idx = (uuid::Uuid::new_v4().as_bytes()[0] as usize) % filtered.len();
454 required_chars.push(filtered[idx]);
455 }
456 }
457 if !exclude_uppercase {
458 chars.push_str(uppercase);
459 let filtered: Vec<char> = uppercase
460 .chars()
461 .filter(|c| !exclude_chars.contains(*c))
462 .collect();
463 if !filtered.is_empty() {
464 let idx = (uuid::Uuid::new_v4().as_bytes()[0] as usize) % filtered.len();
465 required_chars.push(filtered[idx]);
466 }
467 }
468 if !exclude_numbers {
469 chars.push_str(digits);
470 let filtered: Vec<char> = digits
471 .chars()
472 .filter(|c| !exclude_chars.contains(*c))
473 .collect();
474 if !filtered.is_empty() {
475 let idx = (uuid::Uuid::new_v4().as_bytes()[0] as usize) % filtered.len();
476 required_chars.push(filtered[idx]);
477 }
478 }
479 if !exclude_punctuation {
480 chars.push_str(punctuation);
481 let filtered: Vec<char> = punctuation
482 .chars()
483 .filter(|c| !exclude_chars.contains(*c))
484 .collect();
485 if !filtered.is_empty() {
486 let idx = (uuid::Uuid::new_v4().as_bytes()[0] as usize) % filtered.len();
487 required_chars.push(filtered[idx]);
488 }
489 }
490
491 if !exclude_chars.is_empty() {
492 chars = chars
493 .chars()
494 .filter(|c| !exclude_chars.contains(*c))
495 .collect();
496 }
497
498 if chars.is_empty() {
499 return Err(SecretsManagerError::NoValidCharsForPassword);
500 }
501
502 let char_vec: Vec<char> = chars.chars().collect();
503 let mut password: Vec<char> = (0..length)
504 .map(|i| {
505 let idx = (uuid::Uuid::new_v4().as_bytes()[i % 16] as usize) % char_vec.len();
506 char_vec[idx]
507 })
508 .collect();
509
510 if require_each_included_type {
512 for (i, required) in required_chars.iter().enumerate() {
513 if i < password.len() {
514 password[i] = *required;
515 }
516 }
517 }
518
519 Ok(password.into_iter().collect())
520 }
521
522 pub fn put_resource_policy(
523 &mut self,
524 secret_id: &str,
525 resource_policy: &str,
526 ) -> Result<&Secret, SecretsManagerError> {
527 let secret = self.find_secret_mut(secret_id)?;
528 secret.resource_policy = Some(resource_policy.to_string());
529 secret.last_changed_date = Utc::now();
530 let name = secret.name.clone();
531 Ok(self.secrets.get(&name).unwrap())
532 }
533
534 pub fn get_resource_policy(&self, secret_id: &str) -> Result<&Secret, SecretsManagerError> {
535 self.find_secret(secret_id)
536 }
537
538 pub fn delete_resource_policy(
539 &mut self,
540 secret_id: &str,
541 ) -> Result<&Secret, SecretsManagerError> {
542 let secret = self.find_secret_mut(secret_id)?;
543 secret.resource_policy = None;
544 secret.last_changed_date = Utc::now();
545 let name = secret.name.clone();
546 Ok(self.secrets.get(&name).unwrap())
547 }
548
549 pub fn list_secret_version_ids(&self, secret_id: &str) -> Result<&Secret, SecretsManagerError> {
550 self.find_secret(secret_id)
551 }
552
553 pub fn rotate_secret(
554 &mut self,
555 secret_id: &str,
556 rotation_lambda_arn: Option<&str>,
557 rotation_rules: Option<RotationRules>,
558 ) -> Result<(&Secret, String), SecretsManagerError> {
559 let secret = self.find_secret_mut(secret_id)?;
560
561 if secret.deleted_date.is_some() {
562 return Err(SecretsManagerError::SecretMarkedDeleted);
563 }
564
565 if let Some(ref rules) = rotation_rules
567 && let Some(days) = rules.automatically_after_days
568 && (!(1..=1000).contains(&days))
569 {
570 return Err(SecretsManagerError::InvalidRotationDays);
571 }
572
573 if let Some(arn) = rotation_lambda_arn {
574 secret.rotation_lambda_arn = Some(arn.to_string());
575 }
576 if let Some(rules) = rotation_rules {
577 secret.rotation_rules = Some(rules);
578 }
579 secret.rotation_enabled = Some(true);
580
581 let now = Utc::now();
583 let new_version_id = uuid::Uuid::new_v4().to_string();
584
585 if let Some(old_vid) = &secret.current_version_id
587 && let Some(old_version) = secret.versions.get_mut(old_vid)
588 {
589 old_version.version_stages.retain(|s| s != "AWSCURRENT");
590 if !old_version
591 .version_stages
592 .contains(&"AWSPREVIOUS".to_string())
593 {
594 old_version.version_stages.push("AWSPREVIOUS".to_string());
595 }
596 }
597
598 let secret_string = secret
600 .current_version_id
601 .as_ref()
602 .and_then(|vid| secret.versions.get(vid))
603 .and_then(|v| v.secret_string.clone());
604
605 let version = SecretVersion {
606 version_id: new_version_id.clone(),
607 secret_string,
608 secret_binary: None,
609 created_date: now,
610 version_stages: vec!["AWSCURRENT".to_string()],
611 };
612
613 secret.versions.insert(new_version_id.clone(), version);
614 secret.current_version_id = Some(new_version_id.clone());
615 secret.last_changed_date = now;
616 secret.last_rotated_date = Some(now);
617
618 let name = secret.name.clone();
619 Ok((self.secrets.get(&name).unwrap(), new_version_id))
620 }
621
622 pub fn tag_resource(
623 &mut self,
624 secret_id: &str,
625 tags: HashMap<String, String>,
626 ) -> Result<(), SecretsManagerError> {
627 let secret = self.find_secret_mut(secret_id)?;
628 for (k, v) in tags {
629 secret.tags.insert(k, v);
630 }
631 secret.last_changed_date = Utc::now();
632 Ok(())
633 }
634
635 pub fn untag_resource(
636 &mut self,
637 secret_id: &str,
638 tag_keys: &[String],
639 ) -> Result<(), SecretsManagerError> {
640 let secret = self.find_secret_mut(secret_id)?;
641 for key in tag_keys {
642 secret.tags.remove(key);
643 }
644 secret.last_changed_date = Utc::now();
645 Ok(())
646 }
647
648 pub fn update_secret_version_stage(
649 &mut self,
650 secret_id: &str,
651 version_stage: &str,
652 move_to_version_id: Option<&str>,
653 remove_from_version_id: Option<&str>,
654 ) -> Result<&Secret, SecretsManagerError> {
655 let secret = self.find_secret_mut(secret_id)?;
656
657 if version_stage == "AWSCURRENT" && remove_from_version_id.is_none() {
659 let current_vid = secret
660 .versions
661 .values()
662 .find(|v| v.version_stages.contains(&"AWSCURRENT".to_string()))
663 .map(|v| v.version_id.clone());
664 if let Some(vid) = current_vid {
665 return Err(SecretsManagerError::MissingRemoveFromVersionId { vid });
666 }
667 }
668
669 if let Some(remove_vid) = remove_from_version_id {
670 if let Some(version) = secret.versions.get_mut(remove_vid) {
671 version.version_stages.retain(|s| s != version_stage);
672 } else {
673 return Err(SecretsManagerError::NotAValidVersion {
674 version_id: remove_vid.to_string(),
675 });
676 }
677 }
678
679 if let Some(move_vid) = move_to_version_id {
680 if let Some(version) = secret.versions.get_mut(move_vid) {
681 if !version.version_stages.contains(&version_stage.to_string()) {
682 version.version_stages.push(version_stage.to_string());
683 }
684 } else {
685 return Err(SecretsManagerError::NotAValidVersion {
686 version_id: move_vid.to_string(),
687 });
688 }
689 }
690
691 if version_stage == "AWSCURRENT" {
693 if let Some(remove_vid) = remove_from_version_id {
694 let remove_vid = remove_vid.to_string();
695 for version in secret.versions.values_mut() {
697 version.version_stages.retain(|s| s != "AWSPREVIOUS");
698 }
699 if let Some(version) = secret.versions.get_mut(&remove_vid) {
701 version.version_stages.push("AWSPREVIOUS".to_string());
702 }
703 }
704
705 if let Some(move_vid) = move_to_version_id
707 && let Some(version) = secret.versions.get_mut(move_vid)
708 {
709 version.version_stages.retain(|s| s != "AWSPREVIOUS");
710 }
711
712 if let Some(move_vid) = move_to_version_id {
713 secret.current_version_id = Some(move_vid.to_string());
714 }
715 }
716
717 secret.last_changed_date = Utc::now();
718 let name = secret.name.clone();
719 Ok(self.secrets.get(&name).unwrap())
720 }
721
722 pub fn replicate_secret_to_regions(
723 &mut self,
724 secret_id: &str,
725 regions: &[String],
726 ) -> Result<&Secret, SecretsManagerError> {
727 let secret = self.find_secret_mut(secret_id)?;
728
729 for region in regions {
730 if !secret
732 .replication_status
733 .iter()
734 .any(|r| r.region == *region)
735 {
736 secret.replication_status.push(ReplicationStatus {
737 region: region.clone(),
738 status: "InSync".to_string(),
739 status_message: None,
740 kms_key_id: None,
741 last_accessed_date: None,
742 });
743 }
744 }
745
746 secret.last_changed_date = Utc::now();
747 let name = secret.name.clone();
748 Ok(self.secrets.get(&name).unwrap())
749 }
750
751 pub fn remove_regions_from_replication(
752 &mut self,
753 secret_id: &str,
754 regions: &[String],
755 ) -> Result<&Secret, SecretsManagerError> {
756 let secret = self.find_secret_mut(secret_id)?;
757 secret
758 .replication_status
759 .retain(|r| !regions.contains(&r.region));
760 secret.last_changed_date = Utc::now();
761 let name = secret.name.clone();
762 Ok(self.secrets.get(&name).unwrap())
763 }
764
765 fn find_secret(&self, secret_id: &str) -> Result<&Secret, SecretsManagerError> {
766 if let Some(secret) = self.secrets.get(secret_id) {
768 return Ok(secret);
769 }
770 for secret in self.secrets.values() {
772 if secret.arn == secret_id {
773 return Ok(secret);
774 }
775 }
776 Err(SecretsManagerError::SecretNotFound)
777 }
778
779 fn find_secret_mut(&mut self, secret_id: &str) -> Result<&mut Secret, SecretsManagerError> {
780 let name = self.resolve_name(secret_id)?;
781 Ok(self.secrets.get_mut(&name).unwrap())
782 }
783
784 fn resolve_name(&self, secret_id: &str) -> Result<String, SecretsManagerError> {
785 if self.secrets.contains_key(secret_id) {
786 return Ok(secret_id.to_string());
787 }
788 for secret in self.secrets.values() {
789 if secret.arn == secret_id {
790 return Ok(secret.name.clone());
791 }
792 }
793 Err(SecretsManagerError::SecretNotFound)
794 }
795}