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