#[cfg_attr(
docsrs,
doc(cfg(any(feature = "rotate_rusoto", feature = "rotate_aws_sdk")))
)]
#[derive(Debug, Clone)]
pub struct Secret<S> {
pub arn: String,
pub version_id: String,
pub inner: SecretContainer<S>,
}
#[cfg_attr(
docsrs,
doc(cfg(any(feature = "rotate_rusoto", feature = "rotate_aws_sdk")))
)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct SecretContainer<S> {
#[serde(flatten)]
pub data: S,
#[cfg_attr(docsrs, doc(cfg(feature = "rotate_with_preserve")))]
#[cfg(feature = "rotate_with_preserve")]
#[serde(flatten)]
pub o: std::collections::HashMap<String, serde_json::Value>,
}
impl<S> std::ops::Deref for SecretContainer<S> {
type Target = S;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<S> std::ops::DerefMut for SecretContainer<S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
#[cfg_attr(
docsrs,
doc(cfg(any(feature = "rotate_rusoto", feature = "rotate_aws_sdk")))
)]
#[derive(Clone)]
pub struct Smc {
#[cfg(feature = "rotate_aws_sdk")]
aws_sdk_client: super::aws_sdk::SmcClient,
#[cfg(feature = "rotate_rusoto")]
rusoto_client: super::rusoto::SmcClient,
}
impl std::fmt::Debug for Smc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Smc").field("client", &"[...]").finish()
}
}
impl Smc {
pub async fn new(_region: &str) -> anyhow::Result<Self> {
Ok(Self {
#[cfg(feature = "rotate_aws_sdk")]
aws_sdk_client: super::aws_sdk::SmcClient::new().await,
#[cfg(feature = "rotate_rusoto")]
rusoto_client: super::rusoto::SmcClient::new(_region)?,
})
}
pub async fn generate_new_password(
&self,
puncutation: bool,
length: Option<i64>,
) -> anyhow::Result<String> {
#[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
let client = &self.aws_sdk_client;
#[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
let client = &self.rusoto_client;
#[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
client.generate_new_password(puncutation, length).await
}
pub(crate) async fn get_secret_value_current<S: serde::de::DeserializeOwned>(
&self,
secret_id: &str,
) -> anyhow::Result<Secret<S>> {
self.get_secret_value(secret_id, "AWSCURRENT").await
}
pub(crate) async fn get_secret_value_pending<S: serde::de::DeserializeOwned>(
&self,
secret_id: &str,
) -> anyhow::Result<Secret<S>> {
self.get_secret_value(secret_id, "AWSPENDING").await
}
async fn get_secret_value<S: serde::de::DeserializeOwned>(
&self,
secret_id: &str,
version_stage: &str,
) -> anyhow::Result<Secret<S>> {
#[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
let client = &self.aws_sdk_client;
#[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
let client = &self.rusoto_client;
#[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
client.get_secret_value(secret_id, version_stage).await
}
pub(crate) async fn put_secret_value_pending<S: serde::Serialize + Send + Sync>(
&self,
secret_id: &str,
request_token: Option<&str>,
value: &SecretContainer<S>,
) -> anyhow::Result<()> {
use anyhow::Context;
#[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
let client = &self.aws_sdk_client;
#[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
let client = &self.rusoto_client;
#[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
let secret_string: String = serde_json::to_string(value)
.with_context(|| format!("Unable to serialize secret_value with id: {}", secret_id))?;
client
.put_secret_value_pending(secret_id, request_token, &secret_string)
.await
}
pub(crate) async fn set_pending_secret_value_to_current(
&self,
secret_arn: String,
secret_current_version_id: String,
secret_pending_version_id: String,
) -> anyhow::Result<()> {
#[cfg(all(feature = "rotate_aws_sdk", not(feature = "rotate_rusoto")))]
let client = &self.aws_sdk_client;
#[cfg(all(feature = "rotate_rusoto", not(feature = "rotate_aws_sdk")))]
let client = &self.rusoto_client;
#[cfg(all(feature = "rotate_rusoto", feature = "rotate_aws_sdk"))]
compile_error("Only rotate_rusoto or rotate_aws_sdk can be enabled at once");
client
.set_pending_secret_value_to_current(
secret_arn,
secret_current_version_id,
secret_pending_version_id,
)
.await
}
}