Initial version
This commit is contained in:
commit
feed596a95
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
21
Cargo.toml
Normal file
21
Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "sd-credentials"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Mathieu Trossevin <mtrossevin@evolix.fr>"]
|
||||
repository = "https://gitea.evolix.org/mtrossevin/storefd/"
|
||||
description = "A simple crate to recover secrets passed by systemd (or anything else that use $CREDENTIAL_DIRECTORY)."
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
default = []
|
||||
# For some inane reason this seems to also require tokio but I am not adding it as a dependency here as nothing I implement actually require tokio.
|
||||
secret-vault = ["dep:secret-vault", "dep:async-trait"]
|
||||
|
||||
[dependencies]
|
||||
async-trait = { version = "0.1.74", optional = true }
|
||||
cap-std = "2.0.0"
|
||||
secret-vault = { version = "1.10.1", optional = true }
|
||||
secret-vault-value = "0.3.8"
|
65
src/lib.rs
Normal file
65
src/lib.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
#[cfg(feature = "secret-vault")]
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "secret-vault")]
|
||||
use secret_vault::{SecretSource, SecretVaultRef, SecretVaultResult, Secret, SecretMetadata, errors::SecretVaultError};
|
||||
|
||||
use secret_vault_value::SecretValue;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CredentialLoader(cap_std::fs::Dir);
|
||||
|
||||
impl CredentialLoader {
|
||||
pub fn new() -> Option<Self> {
|
||||
let credential_directory = std::env::var_os("CREDENTIALS_DIRECTORY")?;
|
||||
let dir = std::fs::File::open(credential_directory).ok()?;
|
||||
let dir = cap_std::fs::Dir::from_std_file(dir);
|
||||
|
||||
Some(Self(dir))
|
||||
}
|
||||
|
||||
pub fn get_file<P: AsRef<Path>>(&self, credential: P) -> std::io::Result<cap_std::fs::File> {
|
||||
self.0.open(credential)
|
||||
}
|
||||
|
||||
pub fn get<P: AsRef<Path>>(&self, credential: P) -> std::io::Result<SecretValue> {
|
||||
Ok(SecretValue::new(self.0.read(credential)?))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "secret-vault")]
|
||||
#[async_trait::async_trait]
|
||||
impl SecretSource for CredentialLoader {
|
||||
fn name(&self) -> String {
|
||||
"CredentialLoader".to_string()
|
||||
}
|
||||
|
||||
async fn get_secrets(&self, references: &[SecretVaultRef]) -> SecretVaultResult<HashMap<SecretVaultRef, Secret>> {
|
||||
let mut result_map: HashMap<SecretVaultRef, Secret> = HashMap::default();
|
||||
|
||||
for secret_ref in references {
|
||||
let secret_name = secret_ref.key.secret_name.as_ref();
|
||||
let secret_version = secret_ref.key.secret_version.as_ref().map(|sv| format!("_v{sv}")).unwrap_or_default();
|
||||
let secret_file_name = format!("{secret_name}{secret_version}");
|
||||
|
||||
match self.get(secret_file_name) {
|
||||
Ok(secret_value) => {
|
||||
let metadata = SecretMetadata::create_from_ref(secret_ref);
|
||||
result_map.insert(secret_ref.clone(), Secret::new(secret_value, metadata));
|
||||
}
|
||||
Err(err) if secret_ref.required => {
|
||||
return Err(SecretVaultError::DataNotFoundError(
|
||||
secret_vault::errors::SecretVaultDataNotFoundError::new(
|
||||
secret_vault::errors::SecretVaultErrorPublicGenericDetails::new("SECRET_NOT_FOUND".into()),
|
||||
format!(
|
||||
"Secret is required but corresponding file is not available {secret_file_name:?}: {err}"
|
||||
))
|
||||
))
|
||||
}
|
||||
Err(_err) => {}
|
||||
}
|
||||
}
|
||||
todo!();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue