wasmcloud_provider_keyvalue_vault/
config.rs1use core::time::Duration;
5
6use std::collections::HashMap;
7use std::env;
8
9use anyhow::{Context, Result};
10use tracing::warn;
11use url::Url;
12use wasmcloud_provider_sdk::{core::secrets::SecretValue, LinkConfig};
13
14use crate::TOKEN_REFRESH_INTERVAL;
15
16const DEFAULT_VAULT_ADDR: &str = "http://127.0.0.1:8200";
19
20#[derive(Clone, Debug)]
22pub struct Config {
23 pub token: String,
26 pub addr: Url,
29 pub mount: String,
32 pub certs: Vec<String>,
36
37 pub token_increment_ttl: Option<String>,
39
40 pub token_refresh_interval: Option<std::time::Duration>,
42}
43
44impl Default for Config {
45 fn default() -> Self {
47 Self::from_values(&HashMap::new()).unwrap()
48 }
49}
50
51impl Config {
52 pub fn from_link_config(link_config: &LinkConfig) -> Result<Config> {
54 let mut map = HashMap::clone(link_config.config);
55
56 if let Some(token) = env::var("VAULT_TOKEN").ok().or_else(|| {
58 link_config
59 .secrets
60 .get("token")
61 .and_then(SecretValue::as_string)
62 .map(String::from)
63 }) {
64 map.insert("VAULT_TOKEN".into(), token);
65 } else {
66 warn!("Secret value [token] (ENV: VAULT_TOKEN) was not found in env or secrets. Please prefer ENV variables or secrets for sensitive values.")
67 }
68
69 Self::from_values(&map)
70 }
71
72 pub fn from_values(values: &HashMap<String, String>) -> Result<Config> {
76 let addr = env::var("VAULT_ADDR")
77 .ok()
78 .or_else(|| values.get("addr").cloned())
79 .or_else(|| values.get("ADDR").cloned())
80 .unwrap_or_else(|| DEFAULT_VAULT_ADDR.to_string());
81 let addr = addr.parse().unwrap_or_else(|_| {
82 eprintln!(
83 "Could not parse VAULT_ADDR [{addr}] as Url, using default of {DEFAULT_VAULT_ADDR}"
84 );
85 DEFAULT_VAULT_ADDR.parse().unwrap()
86 });
87 let token = env::var("VAULT_TOKEN")
88 .ok()
89 .or_else(|| values.get("token").cloned())
90 .or_else(|| values.get("TOKEN").cloned())
91 .context("missing setting for 'token' or VAULT_TOKEN")?;
92 let mount = env::var("VAULT_MOUNT")
93 .ok()
94 .or_else(|| values.get("mount").cloned())
95 .or_else(|| values.get("MOUNT").cloned())
96 .unwrap_or_else(|| "secret".to_string());
97 let certs = env::var("VAULT_CERTS")
98 .ok()
99 .or_else(|| values.get("certs").cloned())
100 .or_else(|| values.get("CERTS").cloned())
101 .map(|certs| certs.split(',').map(|s| s.trim().to_string()).collect())
102 .unwrap_or_default();
103 Ok(Config {
104 addr,
105 token,
106 mount,
107 certs,
108 token_increment_ttl: env::var("VAULT_TOKEN_INCREMENT_TTL")
109 .ok()
110 .or_else(|| values.get("token_increment_ttl").cloned())
111 .or_else(|| values.get("TOKEN_INCREMENT_TTL").cloned()),
112 token_refresh_interval: match env::var("VAULT_TOKEN_REFRESH_INTERVAL")
113 .ok()
114 .or_else(|| values.get("token_refresh_interval").cloned())
115 .or_else(|| values.get("TOKEN_REFRESH_INTERVAL").cloned())
116 {
117 Some(val) => {
118 let secs = val.parse::<u64>().unwrap_or_else(|_| {
119 eprintln!(
120 "Could not parse VAULT_TOKEN_REFRESH_INTERVAL as u64, using default of {}",
121 TOKEN_REFRESH_INTERVAL.as_secs()
122 );
123 TOKEN_REFRESH_INTERVAL.as_secs()
124 });
125 Some(Duration::from_secs(secs))
126 }
127 _ => None,
128 },
129 })
130 }
131}