Expand description
OS-keyring-backed implementation of evault-core’s
SecretStore trait.
OsKeyringSecretStore delegates to the platform’s native credential
store via the keyring crate:
- Windows: Credential Manager (DPAPI).
- macOS: Keychain.
- Linux/BSD: D-Bus Secret Service (
gnome-keyring,KWallet, …).
Each variable’s value is stored under the canonical service identifier
"evault" keyed by the variable’s UUID. The mapping is one credential
per variable so platform tooling can audit individual secrets.
§Error semantics
Per the evault_core::traits::SecretStore contract:
getreturnsOk(None)when no credential exists for the supplied id. Platform “item not found” codes are the only path to thisNone; every other backend error propagates asevault_core::error::SecretError::Backendorevault_core::error::SecretError::Unavailable.deleteis idempotent: deleting an absent item isOk(()).putalways either writes or returns an error — it never silently fails.
§Operational notes
- Single backend per process.
keyring 4.xkeeps a single process-wide active backend (use_native_store,use_named_store,release_store). This crate initialises it once viastd::sync::OnceLock. Do not call any of those keyring-crate functions yourself in the same process — a host that swaps the backend later may route subsequent operations to an in-memorysamplestore that does not persist. Backend("ambiguous")is a security signal. Because every variable lives at a fixed("evault", <uuid>)pair, an ambiguity error means another application is writing to the same namespace. Treat it as tampering, not as a routine backend error.- Init result is sticky. If the first call fails (e.g. the user hasn’t started gnome-keyring yet), subsequent calls in the same process see the cached failure. A CLI re-launch starts fresh; a daemon would need a future “reset” hook.
§Examples
ⓘ
use evault_core::traits::SecretStore;
use evault_core::crypto::{ExposeSecret, SecretString};
use evault_core::model::VarId;
use evault_store_keyring::OsKeyringSecretStore;
let store = OsKeyringSecretStore::new().expect("init keyring");
let id = VarId::new_v4();
store.put(id, SecretString::from(String::from("hunter2"))).unwrap();
let got = store.get(id).unwrap().expect("present");
assert_eq!(got.expose_secret(), "hunter2");
store.delete(id).unwrap();Structs§
- OsKeyring
Secret Store SecretStoreimpl backed by the platform’s native credential store.