avassa_client/strongbox/
mod.rs1use crate::client::Client;
5use std::collections::HashMap;
6
7use crate::error::{Error, Result};
8
9pub mod tls;
11
12const SBOX_VAULTS: &str = "v1/state/strongbox/vaults";
13
14pub struct Vault {
16 client: Client,
17 vault_url: String,
18}
19
20impl Vault {
21 pub async fn list(client: &Client) -> Result<Vec<String>> {
23 let resp: serde_json::Value = client.get_json(SBOX_VAULTS, Some(&[("keys", "")])).await?;
24
25 resp.as_array()
26 .ok_or_else(|| crate::Error::API("Expected an array".into()))?
27 .iter()
28 .inspect(|s| tracing::debug!("{:#?}", s))
29 .map(|s| {
30 s.as_str()
31 .map(str::to_string)
32 .ok_or_else(|| crate::Error::API("Expected a name".into()))
33 })
34 .collect()
35 }
36
37 pub(crate) async fn open(client: &Client, vault: &str) -> Result<Self> {
38 let vault_url = format!("{SBOX_VAULTS}/{vault}");
39 tracing::debug!("Opening vault at path: {vault_url}");
40 let _vault: serde_json::Value = client.get_json(&vault_url, None).await?;
42 Ok(Self {
43 client: client.clone(),
44 vault_url,
45 })
46 }
47
48 pub async fn open_secrets(&self, name: &str) -> Result<Secrets> {
50 let map_url = format!("{}/secrets/{name}", self.vault_url);
51
52 let json: serde_json::Value = self.client.get_json(&map_url, None).await?;
53
54 let kv = json
55 .as_object()
56 .ok_or_else(|| Error::general("expected a JSON object in secrets"))?;
57
58 let mut cache = HashMap::new();
59 if let Some(data) = kv.get("dict").and_then(serde_json::Value::as_object) {
60 for (k, v) in data {
61 cache.insert(
62 k.clone(),
63 v.as_str()
64 .ok_or_else(|| Error::general("Expected secret value to be a string"))?
65 .to_string(),
66 );
67 }
68 }
69
70 tracing::debug!("Successfully loaded {}", name);
71
72 Ok(Secrets { cache })
73 }
74}
75
76#[derive(Clone)]
78pub struct Secrets {
79 cache: HashMap<String, String>,
80}
81
82impl Secrets {
83 #[must_use]
85 pub fn get(&self, key: &str) -> Option<&String> {
86 self.cache.get(key)
87 }
88}
89
90impl std::fmt::Debug for Secrets {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 f.debug_list().entries(self.cache.keys()).finish()
93 }
94}