neuron_secret_vault/
lib.rs1#![deny(missing_docs)]
2use async_trait::async_trait;
9use layer0::secret::SecretSource;
10use neuron_auth::AuthProvider;
11use neuron_secret::{SecretError, SecretLease, SecretResolver};
12use std::sync::Arc;
13
14pub struct VaultResolver {
16 _addr: String,
17 _auth: Arc<dyn AuthProvider>,
18}
19
20impl VaultResolver {
21 pub fn new(addr: impl Into<String>, auth: Arc<dyn AuthProvider>) -> Self {
23 Self {
24 _addr: addr.into(),
25 _auth: auth,
26 }
27 }
28}
29
30#[async_trait]
31impl SecretResolver for VaultResolver {
32 async fn resolve(&self, source: &SecretSource) -> Result<SecretLease, SecretError> {
33 match source {
34 SecretSource::Vault { mount, path } => Err(SecretError::BackendError(format!(
35 "VaultResolver is a stub — would resolve {mount}/{path}"
36 ))),
37 _ => Err(SecretError::NoResolver("vault".into())),
38 }
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use neuron_auth::{AuthError, AuthRequest, AuthToken};
46
47 struct StubAuth;
48 #[async_trait]
49 impl AuthProvider for StubAuth {
50 async fn provide(&self, _request: &AuthRequest) -> Result<AuthToken, AuthError> {
51 Ok(AuthToken::permanent(b"stub".to_vec()))
52 }
53 }
54
55 fn _assert_send_sync<T: Send + Sync>() {}
56
57 #[test]
58 fn object_safety() {
59 _assert_send_sync::<Box<dyn SecretResolver>>();
60 _assert_send_sync::<Arc<dyn SecretResolver>>();
61 let auth: Arc<dyn AuthProvider> = Arc::new(StubAuth);
62 let resolver = VaultResolver::new("https://vault:8200", auth);
63 let _: Box<dyn SecretResolver> = Box::new(resolver);
64 }
65
66 #[tokio::test]
67 async fn matches_vault_source() {
68 let auth: Arc<dyn AuthProvider> = Arc::new(StubAuth);
69 let resolver = VaultResolver::new("https://vault:8200", auth);
70 let source = SecretSource::Vault {
71 mount: "secret".into(),
72 path: "data/key".into(),
73 };
74 let err = resolver.resolve(&source).await.unwrap_err();
75 assert!(matches!(err, SecretError::BackendError(_)));
76 assert!(err.to_string().contains("stub"));
77 }
78
79 #[tokio::test]
80 async fn rejects_wrong_source() {
81 let auth: Arc<dyn AuthProvider> = Arc::new(StubAuth);
82 let resolver = VaultResolver::new("https://vault:8200", auth);
83 let source = SecretSource::OsKeystore {
84 service: "test".into(),
85 };
86 let err = resolver.resolve(&source).await.unwrap_err();
87 assert!(matches!(err, SecretError::NoResolver(_)));
88 }
89}