use crate::crypto::envelope::EnvelopeService;
use crate::key_provider::KeyProvider;
use crate::spec_compat::{
ContentType, DecryptError, DecryptResult, Result, Scope, SecretListItem, SecretMeta, SecretUri,
SecretVersion, SecretsBackend,
};
#[derive(Debug, Clone)]
pub struct BrokerSecret {
pub version: u64,
pub meta: SecretMeta,
pub payload: Vec<u8>,
}
impl BrokerSecret {
pub fn content_type(&self) -> ContentType {
self.meta.content_type
}
}
pub struct SecretsBroker<B, P>
where
B: SecretsBackend,
P: KeyProvider,
{
backend: B,
crypto: EnvelopeService<P>,
}
impl<B, P> SecretsBroker<B, P>
where
B: SecretsBackend,
P: KeyProvider,
{
pub fn new(backend: B, crypto: EnvelopeService<P>) -> Self {
Self { backend, crypto }
}
pub fn put_secret(&mut self, meta: SecretMeta, data: &[u8]) -> Result<SecretVersion> {
let record = self.crypto.encrypt_record(meta, data)?;
self.backend.put(record)
}
pub fn get_secret(&mut self, uri: &SecretUri) -> DecryptResult<Option<BrokerSecret>> {
self.get_secret_version(uri, None)
}
pub fn get_secret_version(
&mut self,
uri: &SecretUri,
version: Option<u64>,
) -> DecryptResult<Option<BrokerSecret>> {
let entry = self
.backend
.get(uri, version)
.map_err(|err| DecryptError::Crypto(err.to_string()))?;
let Some(entry) = entry else {
return Ok(None);
};
if entry.deleted {
return Ok(None);
}
let record = match entry.record {
Some(record) => record,
None => return Ok(None),
};
let payload = self.crypto.decrypt_record(&record)?;
Ok(Some(BrokerSecret {
version: entry.version,
meta: record.meta.clone(),
payload,
}))
}
pub fn list_secrets(
&self,
scope: &Scope,
category_prefix: Option<&str>,
name_prefix: Option<&str>,
) -> Result<Vec<SecretListItem>> {
self.backend.list(scope, category_prefix, name_prefix)
}
pub fn delete_secret(&self, uri: &SecretUri) -> Result<SecretVersion> {
self.backend.delete(uri)
}
pub fn versions(&self, uri: &SecretUri) -> Result<Vec<SecretVersion>> {
self.backend.versions(uri)
}
pub fn exists(&self, uri: &SecretUri) -> Result<bool> {
self.backend.exists(uri)
}
pub fn backend(&self) -> &B {
&self.backend
}
pub fn crypto(&self) -> &EnvelopeService<P> {
&self.crypto
}
pub fn crypto_mut(&mut self) -> &mut EnvelopeService<P> {
&mut self.crypto
}
}