feat: v1.0.3, add log4rs

This commit is contained in:
2024-11-21 23:00:37 +08:00
parent e2f5bc52a2
commit 7d9f9f6870
9 changed files with 474 additions and 49 deletions

View File

@@ -17,6 +17,7 @@ mod yubikey_hmac;
#[cfg(feature = "yubikey")]
mod yubikey_init_master_key;
mod serve_datakey;
mod serve_log;
pub struct DefaultCommandImpl;
@@ -62,6 +63,8 @@ fn inner_main() -> CommandError {
{
#[cfg(feature = "yubikey")]
features.push("yubikey".to_string());
#[cfg(feature = "harden_process")]
features.push("harden_process".to_string());
}
let long_about = format!("Local mini KMS, features: [{}]", features.join(", "));
let mut app = App::new(env!("CARGO_PKG_NAME"))

View File

@@ -1,5 +1,3 @@
use std::net::SocketAddr;
use clap::{App, Arg, ArgMatches, SubCommand};
use hyper::client::HttpConnector;
use hyper::server::conn::AddrStream;
@@ -8,10 +6,11 @@ use hyper::{Body, Client, Method, Request, Response, Server, StatusCode};
use rust_util::util_clap::{Command, CommandError};
use rust_util::{failure_and_exit, information, success, warning, XResult};
use serde_json::{json, Value};
use std::net::SocketAddr;
use std::sync::atomic::{AtomicU64, Ordering};
use tokio::runtime::Runtime;
use crate::serve_common::{self, GenericError, MemoryKey, Result};
use crate::serve_encrypt_decrypt;
use crate::serve_init;
use crate::serve_init::InitRequest;
use crate::serve_read_write;
@@ -20,6 +19,11 @@ use crate::serve_status;
use crate::yubikey_hmac;
use crate::{db, jose, proc};
use crate::{do_response, serve_datakey};
use crate::{serve_encrypt_decrypt, serve_log};
lazy_static::lazy_static! {
pub static ref GLOBAL_REQUEST_COUNT: AtomicU64 = AtomicU64::new(0);
}
pub struct CommandImpl;
@@ -32,9 +36,18 @@ impl Command for CommandImpl {
.arg(Arg::with_name("local-db").long("local-db").short("d").takes_value(true).default_value("local-mini-kms.db").help("Local db file"))
.arg(Arg::with_name("yubikey-challenge").long("yubikey-challenge").short("c").takes_value(true).help("Yubikey challenge"))
.arg(Arg::with_name("init-encrypted-master-key").long("init-encrypted-master-key").short("k").takes_value(true).help("Init encrypted mater key"))
.arg(Arg::with_name("log-level").long("log-level").takes_value(true).help("Log level: trace, debug, info, warn or error"))
.arg(Arg::with_name("log-file").long("log-file").takes_value(true).help("Log file #DEFAULT or config file"))
}
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
let log_level = sub_arg_matches.value_of("log-level");
let log_file = sub_arg_matches.value_of("log-file");
if let Err(e) = serve_log::init_logger(log_level, log_file) {
println!("[ERROR] Init logger failed: {}", e);
}
let local_mini_kms_db = sub_arg_matches.value_of("local-db").expect("Get local mini kms db error");
match init_instance(local_mini_kms_db) {
Ok(true) => success!("Init server success"),
@@ -61,6 +74,7 @@ impl Command for CommandImpl {
});
let server = Server::bind(&addr).serve(new_service);
information!("Listening on http://{}", addr);
log::info!("Listening on http://{}", addr);
match server.await {
Err(e) => failure_and_exit!("Server error: {}", e),
Ok(_) => success!("Server ended"),
@@ -77,11 +91,13 @@ async fn response_requests(
req: Request<Body>,
_client: Client<HttpConnector>,
) -> Result<Response<Body>> {
let request_idx = GLOBAL_REQUEST_COUNT.fetch_add(1, Ordering::Relaxed);
let process = proc::get_process(remote_addr.port());
match process {
None => information!( "Receive request: {}, from: {}", req.uri(), remote_addr ),
Some(process) => information!(
"Receive request: {}, from: {}, process: {} {} {:?}",
None => log::info!( "Receive request: {}, from: {}", req.uri(), remote_addr ),
Some(process) => log::info!(
"[{:06}] Receive request: {}, from: {}, process: {} {} {:?}",
request_idx,
req.uri(),
remote_addr,
process.pid,

View File

@@ -133,7 +133,7 @@ pub fn byte_to_multi_view_map(bytes: &[u8], with_value: bool) -> Map<String, Val
pub fn open_local_db() -> XResult<Connection> {
let startup_rw_lock = STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error");
match &*startup_rw_lock {
None => simple_error!("Db is not initted!"),
None => simple_error!("Db is not initiated!"),
Some(k) => {
Ok(opt_result!(db::open_db(& k.database_file), "Open db failed: {}"))
}

View File

@@ -5,7 +5,7 @@ use base64::Engine;
use hyper::body::Buf;
use hyper::{Body, Request, Response, StatusCode};
use rand::random;
use rust_util::{debugging, iff, XResult};
use rust_util::{iff, XResult};
use seckey::SecBytes;
use serde_derive::{Deserialize, Serialize};
use serde_json::json;
@@ -32,7 +32,7 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
let whole_body = hyper::body::aggregate(req).await?;
let request: DataKeyRequest = serde_json::from_reader(whole_body.reader())?;
debugging!("Generate data key: {} {}", &request.r#type, &request.spec);
log::debug!("Generate data key: {} {}", &request.r#type, &request.spec);
let key = match get_master_key() {
None => return serve_common::error("status_not_ready"),
Some(key) => key,

View File

@@ -1,6 +1,6 @@
use hyper::body::Buf;
use hyper::{Body, Request, Response, StatusCode};
use rust_util::{debugging, XResult};
use rust_util::XResult;
use serde::{Deserialize, Serialize};
use serde_json::{json, Map, Value};
@@ -21,7 +21,7 @@ async fn inner_decrypt(req: Request<Body>) -> XResult<(StatusCode, Value)> {
let whole_body = hyper::body::aggregate(req).await?;
let data: DecryptRequest = serde_json::from_reader(whole_body.reader())?;
debugging!("To be decrypted value: {}", &data.encrypted_value);
log::debug!("To be decrypted value: {}", &data.encrypted_value);
let key = match get_master_key() {
None => return serve_common::error("status_not_ready"),
Some(key) => key,

View File

@@ -2,7 +2,7 @@ use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use hyper::body::Buf;
use hyper::{Body, Request, Response, StatusCode};
use rust_util::{debugging, information, opt_result, success, warning, XResult};
use rust_util::{opt_result, XResult};
use seckey::SecBytes;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
@@ -48,7 +48,7 @@ pub async fn inner_init_request(init_request: InitRequest) -> XResult<(StatusCod
} else if let Some(clear_master_key_hex) = init_request.clear_master_key_hex {
hex::decode(clear_master_key_hex)?
} else if let Some(encrypted_master_key) = init_request.encrypted_master_key {
debugging!("Received encrypted master key: {}", encrypted_master_key);
log::debug!("Received encrypted master key: {}", encrypted_master_key);
if let Some(k) = &*startup_rw_lock {
let (clear_master_key, _) = jose::deserialize_jwe_rsa(&encrypted_master_key, &k.instance_rsa_key_pair)?;
clear_master_key
@@ -76,19 +76,19 @@ pub async fn inner_init_request(init_request: InitRequest) -> XResult<(StatusCod
db::insert_key(&conn, &key)?;
}
Some(key) => {
debugging!("Found jwe: {}", &key.encrypted_key);
log::debug!("Found jwe: {}", &key.encrypted_key);
let _ = opt_result!(jose::deserialize_jwe_aes(&key.encrypted_key, &clear_master_key), "Deserialize master key verification key failed: {}");
}
}
information!("Set master key success");
log::info!("Set master key success");
#[cfg(feature = "yubikey")]
if let Some(yubikey_challenge) = &init_request.yubikey_challenge {
match yubikey_hmac::yubikey_challenge_as_32_bytes(yubikey_challenge.as_bytes()) {
Err(e) => warning!("Yubikey challenge failed: {}", e),
Err(e) => log::warn!("Yubikey challenge failed: {}", e),
Ok(challenge_key) => match jose::serialize_jwe_aes(&clear_master_key, &challenge_key) {
Err(e) => warning!("Yubikey seal master key failed: {}", e),
Ok(jwe) => success!("Yubikey sealed master key: {}", jwe)
Err(e) => log::warn!("Yubikey seal master key failed: {}", e),
Ok(jwe) => log::info!("Yubikey sealed master key: {}", jwe)
},
}
}

66
src/serve_log.rs Normal file
View File

@@ -0,0 +1,66 @@
use log::LevelFilter;
use rust_util::{simple_error, XResult};
use std::{env, fs};
const DEFAULT_LOG4RS_CONFIG: &str = r##"refresh_rate: 10 seconds
appenders:
file:
kind: rolling_file
path: "log/local_mini_kms_log.log"
append: true
encoder:
pattern: "{d} - {m}{n}"
policy:
kind: compound
trigger:
kind: size
limit: 100 mb
roller:
kind: fixed_window
pattern: log/local_mini_kms_log.{}.log
count: 10
root:
level: info
appenders:
- file"##;
pub fn init_logger(log_level: Option<&str>, log4rs_file: Option<&str>) -> XResult<()> {
match log4rs_file {
None => {
let level = match env::var("LOGGER").ok().as_deref().map(get_log_level_filter) {
Some(Ok(level)) => level,
_ => log_level.map(get_log_level_filter).unwrap_or(Ok(LevelFilter::Debug))?,
};
let _ = env_logger::builder().filter_level(level).try_init();
}
Some(log4rs_file) => {
let log4rs_config_file = if log4rs_file == "#DEFAULT" {
let default_log4rs_file = "default_log4rs.yaml";
let _ = fs::metadata(default_log4rs_file).map_err(|_| {
fs::write(default_log4rs_file, DEFAULT_LOG4RS_CONFIG).map_err(|e| {
println!("Write file: {} failed: {}", default_log4rs_file, e);
})
});
default_log4rs_file
} else {
log4rs_file
};
log4rs::init_file(log4rs_config_file, Default::default())?;
}
}
Ok(())
}
fn get_log_level_filter(log_level: &str) -> XResult<LevelFilter> {
Ok(match log_level {
"trace" => LevelFilter::Trace,
"debug" => LevelFilter::Debug,
"info" => LevelFilter::Info,
"warn" => LevelFilter::Warn,
"error" => LevelFilter::Error,
_ => {
return simple_error!("invalid log_level");
}
})
}