ordinary_storage/stores/
secrets.rs1use anyhow::bail;
6use bytes::Bytes;
7use chacha20poly1305::{
8 KeyInit, XChaCha20Poly1305, XNonce,
9 aead::{Aead, Generate},
10};
11use saferlmdb::{
12 self as lmdb, Database, DatabaseOptions, Environment, ReadTransaction, WriteTransaction, put,
13};
14use std::sync::Arc;
15use tracing::instrument;
16
17pub struct SecretsStore {
18 env: Arc<Environment>,
19
20 secrets_db: Arc<Database<'static>>,
22
23 encryption_key: [u8; 32],
24}
25
26impl SecretsStore {
27 pub fn new(env: &Arc<Environment>, encryption_key: [u8; 32]) -> anyhow::Result<Self> {
28 let secrets_db = Arc::new(Database::open(
29 env.clone(),
30 Some("secrets"),
31 &DatabaseOptions::new(lmdb::db::Flags::CREATE),
32 )?);
33
34 Ok(Self {
35 env: env.clone(),
36 secrets_db,
37 encryption_key,
38 })
39 }
40
41 #[instrument(skip_all, err)]
43 pub fn put(&self, name: &str, value: &[u8]) -> anyhow::Result<()> {
44 tracing::info!(name);
45
46 let cipher = XChaCha20Poly1305::new(&self.encryption_key.into());
47 let nonce = XNonce::generate();
48
49 let txn = WriteTransaction::new(self.env.clone())?;
50
51 {
52 let mut access = txn.access();
53
54 match cipher.encrypt(&nonce, value) {
55 Ok(mut encrypted) => {
56 encrypted.extend_from_slice(&nonce);
57 access.put(
58 &self.secrets_db,
59 name.as_bytes(),
60 &encrypted,
61 &put::Flags::empty(),
62 )?;
63 }
64 Err(err) => bail!("{err}"),
65 }
66 }
67
68 txn.commit()?;
69
70 Ok(())
71 }
72
73 #[instrument(skip_all, err)]
75 pub fn get(&self, name: &str) -> anyhow::Result<Bytes> {
76 tracing::info!(name);
77
78 let cipher = XChaCha20Poly1305::new(&self.encryption_key.into());
79
80 let txn = ReadTransaction::new(self.env.clone())?;
81 let access = txn.access();
82
83 let result = access.get::<[u8], [u8]>(&self.secrets_db, name.as_bytes())?;
84
85 let ciphertext_len = result.len() - 24;
86
87 match cipher.decrypt(
88 &XNonce::try_from(&result[ciphertext_len..])?,
89 &result[..ciphertext_len],
90 ) {
91 Ok(plaintext) => Ok(Bytes::copy_from_slice(plaintext.as_ref())),
92 Err(err) => bail!("{err}"),
93 }
94 }
95}