secret_loader/lib.rs
1// Copyright (c) The secret-loader Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Load secrets from multiple locations
5//!
6//! `secret-loader` provides a [`SecretLoader`] type that can load a [`SecretString`](secrecy::SecretString)
7//! from an environment variable, a file, or directly as a String. The intended use case is to remove
8//! hard-coded credentials in configuration files and replace them with hints on how an application should
9//! load the secret instead. E.g. updating the following TOML configuration file:
10//! ```toml
11//! [user.alice]
12//! username = "alice"
13//! key = "somecrazypassword"
14//!
15//! [user.bob]
16//! username = "bob"
17//! key = "hello123"
18//! ```
19//! With the following configuration file instead:
20//! ```toml
21//! [user.alice]
22//! username = "alice"
23//! key = "env:ALICE_SECRET_KEY"
24//!
25//! [user.bob]
26//! username = "bob"
27//! key = "file:/home/bob/.auth_token"
28//! ```
29//!
30//! # Basic Usage
31//! Continuing with our configuration file above, here is how we could deserialize that TOML
32//!
33//! ```
34//! use std::collections::HashMap;
35//!
36//! use secrecy::ExposeSecret;
37//! use secrecy::SecretString;
38//! use secret_loader::SecretLoader;
39//! use serde::Deserialize;
40//! # use std::env;
41//! #
42//! # env::set_var("ALICE_SECRET_KEY", "somecrazypassword");
43//!
44//! // Somewhere outside this program, the env var `ALICE_SECRET_KEY` has been set
45//!
46//! #[derive(Deserialize)]
47//! pub struct UserConfig {
48//! username: String,
49//! key: SecretLoader,
50//! }
51//!
52//! #[derive(Deserialize)]
53//! pub struct Configuration {
54//! user: HashMap<String, UserConfig>,
55//! }
56//!
57//! let config: Configuration = toml::from_str(r#"
58//! [user.alice]
59//! username = "alice"
60//! key = "env:ALICE_SECRET_KEY"
61//!
62//! [user.bob]
63//! username = "bob"
64//! key = "file:/home/bob/.auth_token"
65//! "#).unwrap();
66//!
67//! let alice_key: SecretString = config.user.get("alice")
68//! .unwrap()
69//! .key.clone()
70//! .into_secret()
71//! .unwrap();
72//! assert_eq!(alice_key.expose_secret(), "somecrazypassword");
73//! ```
74//!
75//! # Deserializing directly to `SecretString`
76//! If you wish to deserialize directly to a `SecretString`, the `#[serde(deserialize_with = "..")]` attribute
77//! can be used to help.
78//!
79//! ```
80//! use std::collections::HashMap;
81//!
82//! use secrecy::ExposeSecret;
83//! use secrecy::SecretString;
84//! use secret_loader::SecretLoader;
85//! use serde::Deserialize;
86//! use serde::Deserializer;
87//! use serde::de::Error as DeError;
88//! # use std::env;
89//! #
90//! # env::set_var("ALICE_SECRET_KEY", "somecrazypassword");
91//!
92//! // Somewhere outside this program, the env var `ALICE_SECRET_KEY` has been set
93//!
94//! #[derive(Deserialize)]
95//! pub struct UserConfig {
96//! username: String,
97//! #[serde(deserialize_with = "deserialize_secret")] // <-- Points at the fn defined below
98//! key: SecretString,
99//! }
100//!
101//! #[derive(Deserialize)]
102//! pub struct Configuration {
103//! user: HashMap<String, UserConfig>,
104//! }
105//!
106//! // New deserialization fn HERE
107//! pub fn deserialize_secret<'de, D>(deserializer: D) -> Result<SecretString, D::Error>
108//! where
109//! D: Deserializer<'de>,
110//! {
111//! SecretLoader::deserialize(deserializer)?.into_secret().map_err(DeError::custom)
112//! }
113//!
114//! let config: Configuration = toml::from_str(r#"
115//! [user.alice]
116//! username = "alice"
117//! key = "env:ALICE_SECRET_KEY"
118//! "#).unwrap();
119//!
120//! let alice_key: SecretString = config.user.get("alice")
121//! .unwrap()
122//! .key.clone();
123//! assert_eq!(alice_key.expose_secret(), "somecrazypassword");
124//! ```
125
126#![warn(missing_docs)]
127// only enables the `doc_cfg` feature when
128// the `docsrs` configuration attribute is defined
129#![cfg_attr(docsrs, feature(doc_cfg))]
130#![doc(html_root_url = "https://docs.rs/secret-loader/0.1.0")]
131
132mod error;
133mod loader;
134#[cfg(feature = "serde")]
135mod serde;
136
137pub use crate::error::LoadError;
138pub use crate::loader::SecretLoader;