use crate::{Secret, SecretManagerError, SecretManagerImpl, SetSecretOutcome};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, convert::Infallible, fmt::Debug, sync::Arc};
use thiserror::Error;
use tokio::sync::RwLock;
#[derive(Clone, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct MemorySecretManagerConfig {
pub secrets: HashMap<String, String>,
pub default: Option<String>,
}
#[derive(Debug, Error)]
pub enum MemorySecretManagerConfigError {
#[error("failed to parse DOCBOX_SECRET_MANAGER_MEMORY_SECRETS")]
ParseSecrets,
}
impl MemorySecretManagerConfig {
pub fn from_env() -> Result<Self, MemorySecretManagerConfigError> {
let default = std::env::var("DOCBOX_SECRET_MANAGER_MEMORY_DEFAULT").ok();
let secrets = match std::env::var("DOCBOX_SECRET_MANAGER_MEMORY_SECRETS") {
Ok(secrets) => serde_json::from_str(&secrets).map_err(|error| {
tracing::error!(?error, "failed to parse memory secrets");
MemorySecretManagerConfigError::ParseSecrets
})?,
Err(_) => Default::default(),
};
Ok(Self { default, secrets })
}
}
impl Debug for MemorySecretManagerConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MemorySecretManagerConfig").finish()
}
}
#[derive(Default, Clone)]
pub struct MemorySecretManager {
inner: Arc<RwLock<MemorySecretManagerInner>>,
}
#[derive(Default)]
struct MemorySecretManagerInner {
data: HashMap<String, Secret>,
default: Option<Secret>,
}
impl MemorySecretManager {
pub fn new(data: HashMap<String, Secret>, default: Option<Secret>) -> Self {
Self {
inner: Arc::new(RwLock::new(MemorySecretManagerInner { data, default })),
}
}
}
pub type MemorySecretError = Infallible;
impl SecretManagerImpl for MemorySecretManager {
async fn get_secret(&self, name: &str) -> Result<Option<super::Secret>, SecretManagerError> {
let inner = &*self.inner.read().await;
if let Some(value) = inner.data.get(name) {
return Ok(Some(value.clone()));
}
if let Some(value) = inner.default.as_ref() {
return Ok(Some(value.clone()));
}
Ok(None)
}
async fn has_secret(&self, name: &str) -> Result<bool, SecretManagerError> {
let inner = &*self.inner.read().await;
Ok(inner.data.contains_key(name))
}
async fn set_secret(
&self,
name: &str,
value: &str,
) -> Result<SetSecretOutcome, SecretManagerError> {
let previous = self
.inner
.write()
.await
.data
.insert(name.to_string(), Secret::String(value.to_string()));
Ok(if previous.is_some() {
SetSecretOutcome::Updated
} else {
SetSecretOutcome::Created
})
}
async fn delete_secret(&self, name: &str, _force: bool) -> Result<(), SecretManagerError> {
self.inner.write().await.data.remove(name);
Ok(())
}
}