Skip to main content

secrets_core/
barrier.rs

1use async_trait::async_trait;
2use std::sync::Arc;
3
4use crate::crypto::Aead;
5use crate::storage::{StorageBackend, StorageEntry, StorageResult};
6
7/// Wraps a raw `StorageBackend`, transparently AEAD-encrypting/decrypting
8/// values. Paths are left in plaintext (same as Vault's own barrier).
9pub struct Barrier<B: StorageBackend> {
10    inner: B,
11    aead: Arc<dyn Aead>,
12}
13
14impl<B: StorageBackend> Barrier<B> {
15    pub fn new(inner: B, aead: Arc<dyn Aead>) -> Self {
16        Self { inner, aead }
17    }
18}
19
20#[async_trait]
21impl<B: StorageBackend> StorageBackend for Barrier<B> {
22    async fn get(&self, path: &str) -> StorageResult<Option<StorageEntry>> {
23        let Some(entry) = self.inner.get(path).await? else {
24            return Ok(None);
25        };
26        let plaintext = self
27            .aead
28            .open(&entry.value)
29            .map_err(|e| crate::storage::StorageError::Backend(e.to_string()))?;
30        Ok(Some(StorageEntry {
31            value: plaintext,
32            expires_at: entry.expires_at,
33        }))
34    }
35
36    async fn put(&self, path: &str, entry: StorageEntry) -> StorageResult<()> {
37        let ciphertext = self
38            .aead
39            .seal(&entry.value)
40            .map_err(|e| crate::storage::StorageError::Backend(e.to_string()))?;
41        self.inner
42            .put(
43                path,
44                StorageEntry {
45                    value: ciphertext,
46                    expires_at: entry.expires_at,
47                },
48            )
49            .await
50    }
51
52    async fn delete(&self, path: &str) -> StorageResult<()> {
53        self.inner.delete(path).await
54    }
55
56    async fn list(&self, prefix: &str) -> StorageResult<Vec<String>> {
57        self.inner.list(prefix).await
58    }
59}