lambda_runtime_types/rotate/
smc.rs

1/// Secret returned by Secret Manager
2#[cfg_attr(
3    docsrs,
4    doc(cfg(any(feature = "rotate_rusoto", feature = "rotate_aws_sdk")))
5)]
6#[derive(Debug, Clone)]
7pub struct Secret<S> {
8    /// Arn to the secret
9    pub arn: String,
10    /// Secret version_id
11    pub version_id: String,
12    /// Inner custom secret
13    pub inner: SecretContainer<S>,
14}
15
16/// Transparent container to inner value.
17/// Prevents accidental override of values not defined by `S`
18#[cfg_attr(
19    docsrs,
20    doc(cfg(any(feature = "rotate_rusoto", feature = "rotate_aws_sdk")))
21)]
22#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
23pub struct SecretContainer<S> {
24    /// Secret data as defined by `S`
25    #[serde(flatten)]
26    pub data: S,
27    /// Other fields not defined by `S`. Necessary to preserve
28    /// available fields, which are not defined in the type.
29    /// Enabled by default with feature `rotate_with_preserve`
30    #[cfg_attr(docsrs, doc(cfg(feature = "rotate_with_preserve")))]
31    #[cfg(feature = "rotate_with_preserve")]
32    #[serde(flatten)]
33    pub o: std::collections::HashMap<String, serde_json::Value>,
34}
35
36impl<S> std::ops::Deref for SecretContainer<S> {
37    type Target = S;
38
39    fn deref(&self) -> &Self::Target {
40        &self.data
41    }
42}
43
44impl<S> std::ops::DerefMut for SecretContainer<S> {
45    fn deref_mut(&mut self) -> &mut Self::Target {
46        &mut self.data
47    }
48}
49
50/// Secret Manager Client
51#[cfg_attr(
52    docsrs,
53    doc(cfg(any(feature = "rotate_rusoto", feature = "rotate_aws_sdk")))
54)]
55#[derive(Clone)]
56pub struct Smc {
57    #[cfg(feature = "rotate_aws_sdk")]
58    aws_sdk_client: super::aws_sdk::SmcClient,
59    #[cfg(feature = "rotate_rusoto")]
60    rusoto_client: super::rusoto::SmcClient,
61}
62
63impl std::fmt::Debug for Smc {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        f.debug_struct("Smc").field("client", &"[...]").finish()
66    }
67}
68
69impl Smc {
70    /// Create a new secret manager client
71    pub async fn new(_region: &str) -> anyhow::Result<Self> {
72        Ok(Self {
73            #[cfg(feature = "rotate_aws_sdk")]
74            aws_sdk_client: super::aws_sdk::SmcClient::new().await,
75            #[cfg(feature = "rotate_rusoto")]
76            rusoto_client: super::rusoto::SmcClient::new(_region)?,
77        })
78    }
79
80    /// Generate a new password
81    pub async fn generate_new_password(
82        &self,
83        puncutation: bool,
84        length: Option<i64>,
85    ) -> anyhow::Result<String> {
86        #[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
87        let client = &self.aws_sdk_client;
88        #[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
89        let client = &self.rusoto_client;
90        #[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
91        compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
92
93        client.generate_new_password(puncutation, length).await
94    }
95
96    /// Fetches the current secret value of the given secret_id
97    pub(crate) async fn get_secret_value_current<S: serde::de::DeserializeOwned>(
98        &self,
99        secret_id: &str,
100    ) -> anyhow::Result<Secret<S>> {
101        self.get_secret_value(secret_id, "AWSCURRENT").await
102    }
103
104    /// Fetches the pending secret value of the given secret_id
105    pub(crate) async fn get_secret_value_pending<S: serde::de::DeserializeOwned>(
106        &self,
107        secret_id: &str,
108    ) -> anyhow::Result<Secret<S>> {
109        self.get_secret_value(secret_id, "AWSPENDING").await
110    }
111
112    async fn get_secret_value<S: serde::de::DeserializeOwned>(
113        &self,
114        secret_id: &str,
115        version_stage: &str,
116    ) -> anyhow::Result<Secret<S>> {
117        #[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
118        let client = &self.aws_sdk_client;
119        #[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
120        let client = &self.rusoto_client;
121        #[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
122        compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
123
124        client.get_secret_value(secret_id, version_stage).await
125    }
126
127    pub(crate) async fn put_secret_value_pending<S: serde::Serialize + Send + Sync>(
128        &self,
129        secret_id: &str,
130        request_token: Option<&str>,
131        value: &SecretContainer<S>,
132    ) -> anyhow::Result<()> {
133        use anyhow::Context;
134
135        #[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
136        let client = &self.aws_sdk_client;
137        #[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
138        let client = &self.rusoto_client;
139        #[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
140        compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
141
142        let secret_string: String = serde_json::to_string(value)
143            .with_context(|| format!("Unable to serialize secret_value with id: {}", secret_id))?;
144        client
145            .put_secret_value_pending(secret_id, request_token, &secret_string)
146            .await
147    }
148
149    pub(crate) async fn set_pending_secret_value_to_current(
150        &self,
151        secret_arn: String,
152        secret_current_version_id: String,
153        secret_pending_version_id: String,
154    ) -> anyhow::Result<()> {
155        #[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
156        let client = &self.aws_sdk_client;
157        #[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
158        let client = &self.rusoto_client;
159        #[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
160        compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
161
162        client
163            .set_pending_secret_value_to_current(
164                secret_arn,
165                secret_current_version_id,
166                secret_pending_version_id,
167            )
168            .await
169    }
170}