//! The swarm's secret-store client: where a credential lives, and how both ends //! reach it. //! //! The HTTP is [`vaultrs`]'s job. What this crate owns is the *agreements* — //! the path a credential is written to and read from ([`path`]), the field its //! bytes live in, and the translation from this deployment's environment into //! a logged-in client ([`client`]). Each of those is a thing the controller and //! a hive must say identically, so it is said once here. pub mod client; pub mod path; pub use client::SecretStore; /// What can go wrong between "we have a client certificate" and "we have the /// credential". #[derive(Debug, thiserror::Error)] pub enum Error { /// A name that would have addressed something other than what the caller /// meant. See [`path`]. #[error("{kind} name {value:?} is not a single path segment of [A-Za-z0-9_-]")] PathSegment { /// Which name was rejected — `agent` or `account`. kind: &'static str, /// The offending value, quoted in the message because the caller /// usually got it from config and needs to see which one. value: String, }, /// A variable the store's address or identity comes from is unset or /// empty. Named rather than defaulted: a wrong store address fails much /// later and much less clearly than a missing one. #[error("{0} is unset or empty")] MissingEnv(&'static str), /// A client-certificate file named by the environment could not be read. #[error("reading {path} (from {var}): {source}")] Identity { /// The variable that named the file. var: &'static str, /// The path it named. path: String, /// The underlying IO failure. source: std::io::Error, }, /// The address would not parse into a URL the client can use. #[error("the store's settings are unusable: {0}")] Settings(String), /// The store refused us, was unreachable, or answered something we could /// not parse. #[error(transparent)] Vault(#[from] Box), /// The client certificate and key did not form a usable identity, or the /// CA bundle did not parse. #[error("building the TLS identity: {0}")] Tls(#[source] reqwest::Error), } impl From for Error { fn from(e: vaultrs::error::ClientError) -> Self { // Boxed because `ClientError` is large enough that carrying it inline // makes every `Result` in the crate pay for the rare arm. Self::Vault(Box::new(e)) } }