pub trait Provider: Send + Sync {
// Required methods
fn get(
&self,
project: &str,
key: &str,
profile: &str,
) -> Result<Option<SecretString>>;
fn set(
&self,
project: &str,
key: &str,
value: &SecretString,
profile: &str,
) -> Result<()>;
fn name(&self) -> &'static str;
fn uri(&self) -> String;
// Provided methods
fn allows_set(&self) -> bool { ... }
fn reflect(&self) -> Result<HashMap<String, Secret>> { ... }
fn get_batch(
&self,
project: &str,
keys: &[&str],
profile: &str,
) -> Result<HashMap<String, SecretString>> { ... }
}Expand description
Trait defining the interface for secret storage providers.
All secret storage backends must implement this trait to integrate with SecretSpec. The trait is designed to be flexible enough to support various storage mechanisms while maintaining a consistent interface.
§Thread Safety
Providers must be Send + Sync as they may be used across thread boundaries
in multi-threaded applications.
§Profile Support
Providers should support profile-based secret isolation, allowing different values for the same key across environments (e.g., development, staging, production).
§Implementation Guidelines
- Providers should handle their own error cases and return appropriate
Resulttypes - Storage paths should follow the pattern:
{provider}/{project}/{profile}/{key} - Providers may choose to be read-only by overriding
allows_set - Provider names should be lowercase and descriptive
Required Methods§
Sourcefn get(
&self,
project: &str,
key: &str,
profile: &str,
) -> Result<Option<SecretString>>
fn get( &self, project: &str, key: &str, profile: &str, ) -> Result<Option<SecretString>>
Retrieves a secret value from the provider.
§Arguments
project- The project namespace for the secretkey- The secret key/name to retrieveprofile- The profile context (e.g., “default”, “production”)
§Returns
Ok(Some(value))if the secret existsOk(None)if the secret doesn’t existErrif there was an error accessing the provider
§Example
match provider.get("myapp", "DATABASE_URL", "production")? {
Some(url) => println!("Database URL: {}", url),
None => println!("DATABASE_URL not found"),
}Sourcefn set(
&self,
project: &str,
key: &str,
value: &SecretString,
profile: &str,
) -> Result<()>
fn set( &self, project: &str, key: &str, value: &SecretString, profile: &str, ) -> Result<()>
Stores a secret value in the provider.
§Arguments
project- The project namespace for the secretkey- The secret key/name to storevalue- The secret value to storeprofile- The profile context (e.g., “default”, “production”)
§Returns
Ok(())if the secret was successfully storedErrif there was an error or the provider is read-only
§Errors
This method should return an error if allows_set returns false.
§Example
provider.set("myapp", "API_KEY", "secret123", "production")?;Provided Methods§
Sourcefn allows_set(&self) -> bool
fn allows_set(&self) -> bool
Returns whether this provider supports setting values.
By default, providers are assumed to support writing. Read-only providers
(like environment variables) should override this to return false.
§Returns
trueif the provider supportssetoperationsfalseif the provider is read-only
§Example
if provider.allows_set() {
provider.set("myapp", "TOKEN", "value", "default")?;
} else {
eprintln!("Provider is read-only");
}Sourcefn reflect(&self) -> Result<HashMap<String, Secret>>
fn reflect(&self) -> Result<HashMap<String, Secret>>
Discovers and returns all secrets available in this provider.
This method is used to introspect the provider and find all available secrets. It’s particularly useful for importing secrets from external sources.
§Returns
A HashMap where keys are secret names and values are Secret configurations.
The default implementation returns an empty map, indicating the provider
doesn’t support reflection.
§Example
let secrets = provider.reflect()?;
for (name, secret) in secrets {
println!("Found secret: {} = {:?}", name, secret);
}Sourcefn get_batch(
&self,
project: &str,
keys: &[&str],
profile: &str,
) -> Result<HashMap<String, SecretString>>
fn get_batch( &self, project: &str, keys: &[&str], profile: &str, ) -> Result<HashMap<String, SecretString>>
Retrieves multiple secrets from the provider in a single batch operation.
This method allows providers to optimize fetching multiple secrets at once, which can significantly improve performance for providers with high latency per request (like cloud-based secret managers).
§Arguments
project- The project namespace for the secretskeys- A slice of secret keys to retrieveprofile- The profile context (e.g., “default”, “production”)
§Returns
A HashMap where keys are the secret names and values are the secret values. Secrets that don’t exist are not included in the result.
§Default Implementation
The default implementation calls get() for each key sequentially.
Providers should override this for better performance when possible.
Trait Implementations§
Source§impl TryFrom<String> for Box<dyn Provider>
impl TryFrom<String> for Box<dyn Provider>
Source§fn try_from(s: String) -> Result<Self>
fn try_from(s: String) -> Result<Self>
Creates a provider instance from a URI string.
This function handles various URI formats and normalizes them before parsing. It supports both full URIs and shorthand notations.
§URI Formats
- Full URI:
scheme://authority/path(e.g.,onepassword://vault/Production)
§Special Cases
- 1password: Will error suggesting to use
onepasswordinstead - Bare provider names: Automatically converted to
provider://
§Examples
use std::convert::TryFrom;
// Simple provider name
let provider = Box::<dyn Provider>::try_from("keyring".to_string())?;
// Full URI with configuration
let provider = Box::<dyn Provider>::try_from("onepassword://vault/Production".to_string())?;
// Dotenv with path
let provider = Box::<dyn Provider>::try_from("dotenv:.env.production".to_string())?;