feat: v1.9.5
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1989,7 +1989,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tiny-encrypt"
|
||||
version = "1.9.4"
|
||||
version = "1.9.5"
|
||||
dependencies = [
|
||||
"aes-gcm-stream",
|
||||
"base64 0.22.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tiny-encrypt"
|
||||
version = "1.9.4"
|
||||
version = "1.9.5"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "A simple and tiny file encrypt tool"
|
||||
|
||||
@@ -101,13 +101,15 @@ fn strip_field(kid: &str, max_len: usize) -> String {
|
||||
|
||||
fn config_profiles(cmd_version: &CmdConfig, config: &TinyEncryptConfig) -> XResult<()> {
|
||||
let mut reverse_map = HashMap::new();
|
||||
for (p, v) in &config.profiles {
|
||||
let mut v2 = v.clone();
|
||||
v2.sort();
|
||||
let vs = v2.join(",");
|
||||
match reverse_map.get_mut(&vs) {
|
||||
None => { reverse_map.insert(vs, vec![(p, v)]); }
|
||||
Some(vec) => { vec.push((p, v)); }
|
||||
if let Some(profiles) = &config.profiles {
|
||||
for (p, v) in profiles {
|
||||
let mut v2 = v.clone();
|
||||
v2.sort();
|
||||
let vs = v2.join(",");
|
||||
match reverse_map.get_mut(&vs) {
|
||||
None => { reverse_map.insert(vs, vec![(p, v)]); }
|
||||
Some(vec) => { vec.push((p, v)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,4 +155,4 @@ fn config_profiles(cmd_version: &CmdConfig, config: &TinyEncryptConfig) -> XResu
|
||||
println!("{}", table);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
187
src/config.rs
187
src/config.rs
@@ -8,7 +8,7 @@ use rust_util::util_file::resolve_file_path;
|
||||
use rust_util::{debugging, opt_result, simple_error, warning, XResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::consts::{TINY_ENC_CONFIG_FILE, TINY_ENC_CONFIG_FILE_2, TINY_ENC_FILE_EXT};
|
||||
use crate::consts::{TINY_ENC_CONFIG_FILE, TINY_ENC_CONFIG_FILE_2, TINY_ENC_CONFIG_FILE_3, TINY_ENC_FILE_EXT};
|
||||
use crate::spec::TinyEncryptEnvelopType;
|
||||
|
||||
/// Config file sample:
|
||||
@@ -39,8 +39,18 @@ use crate::spec::TinyEncryptEnvelopType;
|
||||
pub struct TinyEncryptConfig {
|
||||
pub environment: Option<HashMap<String, StringOrVecString>>,
|
||||
pub namespaces: Option<HashMap<String, String>>,
|
||||
pub includes: Option<String>, // find all *.tinyencrypt.json
|
||||
pub envelops: Vec<TinyEncryptConfigEnvelop>,
|
||||
pub profiles: HashMap<String, Vec<String>>,
|
||||
pub profiles: Option<HashMap<String, Vec<String>>>,
|
||||
}
|
||||
|
||||
impl TinyEncryptConfig {
|
||||
fn get_profile(&self, profile: &str) -> Option<&Vec<String>> {
|
||||
match &self.profiles {
|
||||
Some(profiles) => profiles.get(profile),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@@ -68,14 +78,18 @@ impl TinyEncryptConfig {
|
||||
pub fn load_default() -> XResult<Self> {
|
||||
let resolved_file = resolve_file_path(TINY_ENC_CONFIG_FILE);
|
||||
let resolved_file_2 = resolve_file_path(TINY_ENC_CONFIG_FILE_2);
|
||||
let resolved_file_3 = resolve_file_path(TINY_ENC_CONFIG_FILE_3);
|
||||
let config_file = if fs::metadata(&resolved_file).is_ok() {
|
||||
debugging!("Load config from: {resolved_file}");
|
||||
resolved_file
|
||||
} else if fs::metadata(&resolved_file_2).is_ok() {
|
||||
debugging!("Load config from: {resolved_file_2}");
|
||||
resolved_file_2
|
||||
} else if fs::metadata(&resolved_file_3).is_ok() {
|
||||
debugging!("Load config from: {resolved_file_3}");
|
||||
resolved_file_3
|
||||
} else {
|
||||
warning!("Cannot find config file from:\n- {resolved_file}\n- {resolved_file_2}");
|
||||
warning!("Cannot find config file from:\n- {resolved_file}\n- {resolved_file_2}\n- {resolved_file_3}");
|
||||
resolved_file
|
||||
};
|
||||
Self::load(&config_file)
|
||||
@@ -88,26 +102,29 @@ impl TinyEncryptConfig {
|
||||
"Read config file: {}, failed: {}",
|
||||
file
|
||||
);
|
||||
let mut config: TinyEncryptConfig = opt_result!(
|
||||
// serde_json::from_str(&config_contents),
|
||||
json5::from_str(&config_contents),
|
||||
let config: TinyEncryptConfig = opt_result!(
|
||||
serde_json::from_str(&config_contents),
|
||||
"Parse config file: {}, failed: {}",
|
||||
file
|
||||
);
|
||||
let mut splited_profiles = HashMap::new();
|
||||
for (k, v) in config.profiles.into_iter() {
|
||||
if !k.contains(',') {
|
||||
splited_profiles.insert(k, v);
|
||||
} else {
|
||||
k.split(',')
|
||||
.map(|k| k.trim())
|
||||
.filter(|k| !k.is_empty())
|
||||
.for_each(|k| {
|
||||
splited_profiles.insert(k.to_string(), v.clone());
|
||||
});
|
||||
let mut config = load_includes_and_merge(config);
|
||||
|
||||
if let Some(profiles) = config.profiles {
|
||||
let mut splited_profiles = HashMap::new();
|
||||
for (k, v) in profiles.into_iter() {
|
||||
if !k.contains(',') {
|
||||
splited_profiles.insert(k, v);
|
||||
} else {
|
||||
k.split(',')
|
||||
.map(|k| k.trim())
|
||||
.filter(|k| !k.is_empty())
|
||||
.for_each(|k| {
|
||||
splited_profiles.insert(k.to_string(), v.clone());
|
||||
});
|
||||
}
|
||||
}
|
||||
config.profiles = Some(splited_profiles);
|
||||
}
|
||||
config.profiles = splited_profiles;
|
||||
|
||||
if let Some(environment) = &config.environment {
|
||||
for (k, v) in environment {
|
||||
@@ -221,7 +238,7 @@ impl TinyEncryptConfig {
|
||||
self.envelops.iter().for_each(|e| {
|
||||
key_ids.push(e.kid.to_string());
|
||||
});
|
||||
} else if let Some(kids) = self.profiles.get(profile) {
|
||||
} else if let Some(kids) = self.get_profile(profile) {
|
||||
kids.iter().for_each(|k| key_ids.push(k.to_string()));
|
||||
}
|
||||
}
|
||||
@@ -275,3 +292,135 @@ pub fn resolve_path_namespace(
|
||||
Some(config) => config.resolve_path_namespace(path, append_te),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_includes_and_merge(mut config: TinyEncryptConfig) -> TinyEncryptConfig {
|
||||
if let Some(includes) = &config.includes {
|
||||
let sub_configs = search_include_configs(&includes);
|
||||
debugging!(
|
||||
"Found {} sub configs, detail {:?}",
|
||||
sub_configs.len(),
|
||||
sub_configs
|
||||
);
|
||||
for sub_config in &sub_configs {
|
||||
// merge environment
|
||||
if let Some(sub_environment) = &sub_config.environment {
|
||||
match &mut config.environment {
|
||||
None => {
|
||||
config.environment = Some(sub_environment.clone());
|
||||
}
|
||||
Some(env) => {
|
||||
for (k, v) in sub_environment {
|
||||
match env.get_mut(k) {
|
||||
None => {
|
||||
env.insert(k.clone(), v.clone());
|
||||
}
|
||||
Some(env_val) => {
|
||||
match (env_val, v) {
|
||||
(StringOrVecString::Vec(env_value_vec), StringOrVecString::Vec(v_vec)) => {
|
||||
for vv in v_vec {
|
||||
if !env_value_vec.contains(vv) {
|
||||
env_value_vec.push(vv.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warning!("Duplicate or mis-match environment value, key: {}", k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// merge profiles
|
||||
for sub_envelop in &sub_config.envelops {
|
||||
let filter_envelops = config.envelops.iter().filter(|e| {
|
||||
e.kid == sub_envelop.kid || (e.sid.is_some() && e.sid == sub_envelop.sid)
|
||||
}).collect::<Vec<_>>();
|
||||
if !filter_envelops.is_empty() {
|
||||
warning!("Duplication kid: {} or sid: {:?}", sub_envelop.kid, sub_envelop.sid);
|
||||
continue;
|
||||
}
|
||||
config.envelops.push(sub_envelop.clone());
|
||||
}
|
||||
// merge profiles
|
||||
if let Some(sub_profiles) = &sub_config.profiles {
|
||||
match &mut config.profiles {
|
||||
None => {
|
||||
config.profiles = Some(sub_profiles.clone());
|
||||
}
|
||||
Some(profiles) => {
|
||||
for (k, v) in sub_profiles {
|
||||
match profiles.get_mut(k) {
|
||||
None => {
|
||||
profiles.insert(k.clone(), v.clone());
|
||||
}
|
||||
Some(env_val) => {
|
||||
for vv in v {
|
||||
env_val.push(vv.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(profiles) = &mut config.profiles {
|
||||
let all_key_ids = config.envelops.iter().map(|e| e.kid.clone()).collect::<Vec<_>>();
|
||||
if profiles.contains_key("__all__") {
|
||||
warning!("Key __all__ in profiles exists")
|
||||
} else {
|
||||
profiles.insert("__all__".to_string(), all_key_ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
pub fn search_include_configs(includes_path: &str) -> Vec<TinyEncryptConfig> {
|
||||
let mut sub_configs = vec![];
|
||||
let read_dir = match fs::read_dir(includes_path) {
|
||||
Ok(read_dir) => read_dir,
|
||||
Err(e) => {
|
||||
warning!("Read dir: {}, failed: {}", includes_path, e);
|
||||
return sub_configs;
|
||||
}
|
||||
};
|
||||
for entry in read_dir {
|
||||
let entry = match entry {
|
||||
Ok(entry) => entry,
|
||||
Err(e) => {
|
||||
warning!("Read dir: {} entry, failed: {}", includes_path, e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let file_name = entry.file_name();
|
||||
let file_name = file_name.to_str();
|
||||
let file_name = match file_name {
|
||||
Some(file_name) => file_name,
|
||||
None => continue,
|
||||
};
|
||||
if file_name.ends_with(".tinyencrypt.json") {
|
||||
debugging!("Matches config file: {}", file_name);
|
||||
let file_path = entry.path();
|
||||
let content = match fs::read_to_string(entry.path()) {
|
||||
Ok(content) => content,
|
||||
Err(e) => {
|
||||
warning!("Read config file: {:?}, failed: {}", file_path, e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let config = match serde_json::from_str::<TinyEncryptConfig>(&content) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
warning!("Parse config file: {:?}, failed: {}", file_path, e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
sub_configs.push(config);
|
||||
}
|
||||
}
|
||||
sub_configs
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ pub const ENC_CHACHA20_POLY1305_KYBER1204: &str = "chacha20-poly1305-kyber1204";
|
||||
pub const TINY_ENC_FILE_EXT: &str = ".tinyenc";
|
||||
pub const TINY_ENC_PEM_FILE_EXT: &str = ".tinyenc.pem";
|
||||
pub const TINY_ENC_CONFIG_FILE: &str = "~/.tinyencrypt/config-rs.json";
|
||||
pub const TINY_ENC_CONFIG_FILE_2: &str = "/etc/tinyencrypt/config-rs.json";
|
||||
pub const TINY_ENC_CONFIG_FILE_2: &str = "~/.config/tinyencrypt-rs.json";
|
||||
pub const TINY_ENC_CONFIG_FILE_3: &str = "/etc/tinyencrypt/config-rs.json";
|
||||
|
||||
pub const TINY_ENC_PEM_NAME: &str = "TINY ENCRYPT";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user