1use std::borrow::Cow;
2use std::env::var;
3use std::error::Error;
4use std::fmt::Display;
5use std::fs::read_to_string;
6
7#[derive(Debug)]
8pub enum SecretError {
9 Load { path: String, error: std::io::Error },
10 MissingEnvVar(String),
11}
12
13impl Display for SecretError {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 match self {
16 SecretError::Load { path, error } => {
17 write!(f, "failed to load token from {path}: {error:#}")
18 }
19 SecretError::MissingEnvVar(var) => {
20 write!(f, "environment variable {var} referenced but not set")
21 }
22 }
23 }
24}
25
26impl Error for SecretError {}
27
28pub fn load(path: &str) -> Result<String, SecretError> {
35 let file = if path.contains("$CREDENTIALS_DIRECTORY") {
36 let dir = var("CREDENTIALS_DIRECTORY")
37 .map_err(|_| SecretError::MissingEnvVar("$CREDENTIALS_DIRECTORY".into()))?;
38 Cow::Owned(path.replace("$CREDENTIALS_DIRECTORY", &dir))
39 } else {
40 Cow::Borrowed(path)
41 };
42
43 let mut content = read_to_string(file.as_ref()).map_err(|error| SecretError::Load {
44 path: file.into(),
45 error,
46 })?;
47
48 content.truncate(content.trim_end().len()); Ok(content)
50}