neuron_secret_keystore/
lib.rs1#![deny(missing_docs)]
2use async_trait::async_trait;
11use layer0::secret::SecretSource;
12use neuron_secret::{SecretError, SecretLease, SecretResolver};
13
14pub struct KeystoreResolver;
16
17impl KeystoreResolver {
18 pub fn new() -> Self {
20 Self
21 }
22}
23
24impl Default for KeystoreResolver {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30#[async_trait]
31impl SecretResolver for KeystoreResolver {
32 async fn resolve(&self, source: &SecretSource) -> Result<SecretLease, SecretError> {
33 match source {
34 SecretSource::OsKeystore { service } => Err(SecretError::BackendError(format!(
35 "KeystoreResolver is a stub — would resolve service {service:?}"
36 ))),
37 _ => Err(SecretError::NoResolver("os_keystore".into())),
38 }
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use std::sync::Arc;
46
47 fn _assert_send_sync<T: Send + Sync>() {}
48
49 #[test]
50 fn object_safety() {
51 _assert_send_sync::<Box<dyn SecretResolver>>();
52 _assert_send_sync::<Arc<dyn SecretResolver>>();
53 let _: Arc<dyn SecretResolver> = Arc::new(KeystoreResolver::new());
54 }
55
56 #[tokio::test]
57 async fn matches_keystore_source() {
58 let resolver = KeystoreResolver::new();
59 let source = SecretSource::OsKeystore {
60 service: "my-app".into(),
61 };
62 let err = resolver.resolve(&source).await.unwrap_err();
63 assert!(matches!(err, SecretError::BackendError(_)));
64 assert!(err.to_string().contains("stub"));
65 }
66
67 #[tokio::test]
68 async fn rejects_wrong_source() {
69 let resolver = KeystoreResolver::new();
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::NoResolver(_)));
76 }
77}