Skip to main content

Vault

Struct Vault 

Source
pub struct Vault { /* private fields */ }
Expand description

A secret in Vault’s KV v2 store, as a configuration source.

Not Clone: the session holds the current token, and two clones sharing a path while logging in separately would double the login traffic and halve the usefulness of the cache. Wrap it in an Arc if two places need one.

Implementations§

Source§

impl Vault

Source

pub fn new( address: impl Into<String>, mount: impl Into<String>, path: impl Into<Keys>, ) -> Self

A secret at {mount}/{path}, served by the Vault at address.

path is a path — "myapp/db" — or a Keys, for the several-paths form.

The document is wrapped under the section key the configuration type uses — "db" by default, changed with with_key — because Vault stores a section’s contents, not a whole file. Several paths all land under that one key and merge, later winning.

Source

pub fn with_key(self, key: impl Into<String>) -> Self

The section key to wrap the secret under.

Must match the key the config type’s builder(..) was given.

Source

pub fn with_token(self, token: impl Into<String>) -> Self

A token somebody already obtained.

Shorthand for with_auth(Auth::token(..)). A renewable token is still renewed; a token that stops working cannot be replaced, because there are no credentials here to log in again with. Every other Auth can.

Source

pub fn with_auth(self, auth: Auth) -> Self

How to obtain a token.

// In Kubernetes, with no secret to distribute at all.
let vault = Vault::new("https://vault.internal:8200", "secret", "myapp/db")
    .with_auth(Auth::kubernetes("myapp"));

// Or AppRole, for a service outside it.
let vault = Vault::new("https://vault.internal:8200", "secret", "myapp/db")
    .with_auth(Auth::app_role(
        std::env::var("VAULT_ROLE_ID").unwrap(),
        std::env::var("VAULT_SECRET_ID").unwrap(),
    ));

Logging in is lazy: this reaches nothing, and the first read does it.

Source

pub fn with_agent(self, agent: Agent) -> Self

Uses an HTTP client the program already has.

For a caller with its own proxy settings, a private CA, a client certificate, or a connection pool it would rather not have a second copy of. The agent’s own timeout applies instead of with_timeout.

let vault = Vault::new("https://vault.internal:8200", "secret", "myapp/db")
    .with_agent(agent);

The escape hatch, and it stays one: with_tls covers a private CA and a client certificate, and everything else — a proxy, a connection pool, an option this crate has never heard of — still lives here. Setting both is refused rather than resolved; see with_tls.

Source

pub fn with_tls(self, tls: TlsConfig) -> Self

A private certificate authority, a client certificate, or both.

The same three settings, spelled the same way, in all seven store crates — and spelled as data, so nothing here names a ureq type:

let vault = Vault::new("https://vault.internal:8200", "secret", "myapp/db")
    .with_token(std::env::var("VAULT_TOKEN").unwrap())
    .with_tls(
        TlsConfig::new()
            .with_ca_certificate_file("/etc/ssl/private-ca.pem")
            .with_client_certificate_files("/etc/ssl/app.crt", "/etc/ssl/app.key"),
    );

Vault expresses all of it: a CA from a file or from bytes, and a client certificate from either. A CA replaces the platform trust store rather than adding to it — naming a private authority is saying the public ones do not apply to this host — so a deployment that needs both puts both in the file.

There is no way to turn verification off. The reasoning is in TlsConfig’s own documentation, and the short version is that the answer to a self-signed server is to trust its certificate, not to stop checking.

Nothing is read here. The files are opened when the first request builds the client, so a missing CA is an error naming the path rather than a panic in a builder chain — the same laziness every other constructor in this family has.

§With with_agent

Setting both is refused, at the first request, naming both calls. An agent already carries a complete TLS configuration, so “apply this too” has no meaning that is not a guess — and the guess that loses silently discards a CA, which is the failure this whole surface exists to prevent. Put the CA on the agent, or drop the agent.

Source

pub fn with_namespace(self, namespace: impl Into<String>) -> Self

The Vault Enterprise namespace, if there is one.

Source

pub fn with_timeout(self, timeout: Duration) -> Self

How long a single fetch may take before it is given up on. Ten seconds by default.

The deadline for one fetch attempt, excluding retries the underlying client performs — the same sentence every store in this family answers to. ureq performs none of its own, so here the deadline is the whole story.

It bounds each request watch makes — the metadata check, and the read that follows a version change — not the loop, which runs until it is stopped.

Source

pub fn reporting_to(self, sink: RemoteSink) -> Self

Reports the watch loop’s failed attempts to sink.

A watch loop is the half of a store dynamic-config cannot otherwise see. RemoteSink::apply records a delivery, so a working watch keeps RemoteStatus current — but a loop whose metadata poll is failing, whose Vault is sealed or whose token was refused delivers nothing, and without this says nothing: dynamic_config_remote_up would report the last delivery rather than the last attempt, and a Vault that stopped answering an hour ago would look healthy until something called refresh_remote.

That gap is wider here than anywhere else in this family, because this watch is a poll of a version counter: a secret that has not changed is never read, so a healthy Vault and a Vault whose token expired yesterday deliver exactly the same thing — nothing.

let sink = DbConfig::remote_sink();

Vault::new(address, "secret", "myapp/db")
    .with_token(std::env::var("VAULT_TOKEN").unwrap())
    .reporting_to(sink)
    .watch(&watching, Duration::from_secs(30), move |document| sink.apply(document))

One sink serves both halves, and it is taken once, where the loop is wired: a sink is Copy, and the generation it captures there is what fences a loop winding down after its source was replaced from charging its failures to the replacement.

A failure to report a failure never reaches the loop — reporting is infallible and silent — and what it moves is deliberately narrow: the failure streak and the last failure, never the fetch clock. So dynamic_config_remote_last_fetch_seconds keeps ageing while dynamic_config_remote_up goes to zero, which is the pair that says both the store is not answering and how stale what it last said has become.

A fetch needs none of this: a fetch records itself, through the Remote that performed it.

Source

pub fn watch<F>( &self, watching: &Watching, interval: Duration, on_change: F, ) -> Result<(), Error>
where F: FnMut(Fetched) -> Result<(), Error>,

Calls on_change when the secret’s version moves, checking every interval.

Polling, because Vault offers nothing better — and metadata polling, because reading a secret every thirty seconds to discover it has not changed is a poor thing to do to a secrets store. Each tick reads {mount}/metadata/{path} for current_version; only a new version triggers a read of the secret itself.

The current value is not delivered at startup, for the same reason a file watcher does not report an edit when it starts. Fetch first if the starting value matters, which it usually does:

sink.apply(vault.fetch()?)?;
vault.watch(&watching, Duration::from_secs(30), move |document| sink.apply(document))

A failed check does not end the watch — an expired token, a sealed Vault, a network blip — it waits out the interval and tries again. stop is noticed within a quarter second regardless of how long interval is.

Surviving a failure quietly is not the same as hiding it: reporting_to hands each failed attempt to a RemoteSink, so a loop that has been failing for an hour stops reporting the store as healthy.

§Errors

If the source reads several paths: the counter this polls belongs to one secret, and a set of secrets has none of its own. Or if the mount turns out not to be KV v2: a v1 mount has no version counter, so every tick would find “no change” and the watch would silently never fire — a misconfiguration, reported as one. Or if on_change returns an error, which ends the watch — so a caller that wants to survive a bad document should log it and return Ok. Transport failures do not surface here; they are retried.

Trait Implementations§

Source§

impl Debug for Vault

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl RemoteSource for Vault

Source§

fn fetch(&self) -> Result<Fetched, Error>

Reads the current document. Read more
Source§

fn describe(&self) -> String

How to name this source in an error or a report.

Auto Trait Implementations§

§

impl !Freeze for Vault

§

impl !RefUnwindSafe for Vault

§

impl !UnwindSafe for Vault

§

impl Send for Vault

§

impl Sync for Vault

§

impl Unpin for Vault

§

impl UnsafeUnpin for Vault

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Paint for T
where T: ?Sized,

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.