bxcore, gatewayd, loopd: the secret store moves to bxcore::secrets
Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use bxcore::secrets::{SecretSource, SecretSpec};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
@@ -39,26 +40,6 @@ pub struct MattermostConfig {
|
||||
pub ca_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Where one secret comes from: exactly one of the three is set (checked by `Config::load`).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct SecretSpec {
|
||||
#[serde(default)]
|
||||
pub credential: Option<String>,
|
||||
#[serde(default)]
|
||||
pub env: Option<String>,
|
||||
#[serde(default)]
|
||||
pub file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// A checked `SecretSpec`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum SecretSource {
|
||||
Credential(String),
|
||||
Env(String),
|
||||
File(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct AllowConfig {
|
||||
@@ -267,66 +248,6 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl SecretSpec {
|
||||
/// Exactly one source, well formed.
|
||||
pub fn source(&self) -> Result<SecretSource, String> {
|
||||
// Exactly one of the three set, else "needs exactly one of credential, env and file".
|
||||
// credential: not empty, only ASCII letters, digits, _ . -. env: not empty, only A-Z, 0-9,
|
||||
// _. file: an absolute path. The messages are in the task.
|
||||
let mut count = 0;
|
||||
if self.credential.is_some() {
|
||||
count += 1;
|
||||
}
|
||||
if self.env.is_some() {
|
||||
count += 1;
|
||||
}
|
||||
if self.file.is_some() {
|
||||
count += 1;
|
||||
}
|
||||
if count != 1 {
|
||||
return Err("needs exactly one of credential, env and file".to_string());
|
||||
}
|
||||
if let Some(credential) = &self.credential {
|
||||
if credential.is_empty()
|
||||
|| !credential.bytes().all(|b| {
|
||||
b.is_ascii_alphabetic() || b.is_ascii_digit() || matches!(b, b'_' | b'.' | b'-')
|
||||
})
|
||||
{
|
||||
return Err(format!(
|
||||
"credential {:?} is not a credential name (letters, digits, _ . -)",
|
||||
credential
|
||||
));
|
||||
}
|
||||
return Ok(SecretSource::Credential(credential.clone()));
|
||||
}
|
||||
if let Some(env) = &self.env {
|
||||
if env.is_empty()
|
||||
|| !env
|
||||
.bytes()
|
||||
.all(|b| matches!(b, b'A'..=b'Z' | b'0'..=b'9' | b'_'))
|
||||
{
|
||||
return Err(format!(
|
||||
"env {:?} is not a variable name (A-Z, 0-9, _)",
|
||||
env
|
||||
));
|
||||
}
|
||||
return Ok(SecretSource::Env(env.clone()));
|
||||
}
|
||||
// `count == 1` and the two above are `None`, so this is `Some`.
|
||||
let file = match &self.file {
|
||||
Some(file) => file,
|
||||
None => return Err("needs exactly one of credential, env and file".to_string()),
|
||||
};
|
||||
if !file.is_absolute() {
|
||||
return Err(format!(
|
||||
"file {:?} must be an absolute path",
|
||||
file.display()
|
||||
));
|
||||
}
|
||||
Ok(SecretSource::File(file.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
/// A Mattermost id: 26 characters of `a-z0-9`.
|
||||
pub fn valid_id(id: &str) -> bool {
|
||||
// 26 bytes, each a-z or 0-9.
|
||||
|
||||
Reference in New Issue
Block a user