Files
local-mini-kms/src/serve_common.rs

158 lines
4.6 KiB
Rust

use std::sync::Mutex;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use hyper::StatusCode;
use rsa::RsaPrivateKey;
use rusqlite::Connection;
use rust_util::{opt_result, simple_error, XResult};
use seckey::SecBytes;
use serde::{Deserialize, Serialize};
use serde_json::{json, Map, Value};
use crate::db;
pub type GenericError = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T> = std::result::Result<T, GenericError>;
#[macro_export]
macro_rules! do_response {
($ex: expr) => (
match $ex {
Ok((status_code, body)) => Ok(Response::builder().status(status_code).body((serde_json::to_string_pretty(&body)? + "\n").into())?),
Err(e) => Ok(Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(
format!("{}\n", serde_json::to_string_pretty(&json!({
"error": "internal_error",
"error_message": format!("{}", e),
}))?).into()
)?),
}
)
}
pub fn ok(body: Value) -> XResult<(StatusCode, Value)> {
Ok((StatusCode::OK, body))
}
pub fn client_error(error: &str) -> XResult<(StatusCode, Value)> {
Ok((
StatusCode::BAD_REQUEST,
json!({ "error": error })
))
}
pub fn server_error(error: &str) -> XResult<(StatusCode, Value)> {
Ok((
StatusCode::INTERNAL_SERVER_ERROR,
json!({ "error": error })
))
}
// pub fn bad_request(error: &str, error_message: &str) -> XResult<(StatusCode, Value)> {
// Ok((
// StatusCode::BAD_REQUEST,
// json!({ "error": error, "error_message": error_message })
// ))
// }
pub struct MemoryKey {
pub database_file: String,
pub instance_rsa_key_pair: RsaPrivateKey,
pub master_key: Option<SecBytes>,
}
lazy_static::lazy_static! {
pub static ref STATUP_RW_LOCK: Mutex<Option<MemoryKey>> = Mutex::new(None);
}
#[derive(Serialize, Deserialize)]
pub struct MultipleViewValue {
pub value: Option<String>,
pub value_hex: Option<String>,
pub value_base64: Option<String>,
}
impl MultipleViewValue {
pub fn from(v: &[u8]) -> Self {
Self {
value: Some(String::from_utf8_lossy(v).to_string()),
value_hex: Some(hex::encode(v)),
value_base64: Some(STANDARD.encode(v)),
}
}
pub fn from_without_value(v: &[u8]) -> Self {
Self {
value: None,
value_hex: Some(hex::encode(v)),
value_base64: Some(STANDARD.encode(v)),
}
}
pub fn to_bytes(&self) -> XResult<Vec<u8>> {
if let Some(v) = &self.value {
Ok(v.as_bytes().to_vec())
} else if let Some(v) = &self.value_hex {
let v = opt_result!(hex::decode(v), "Decode hex failed: {}");
Ok(v)
} else if let Some(v) = &self.value_base64 {
let v = opt_result!(STANDARD.decode(v), "Decode base64 failed: {}");
Ok(v)
} else {
simple_error!("Multiple view value is all empty")
}
}
}
#[macro_export] macro_rules! require_master_key {
() => {
match $crate::serve_common::get_master_key() {
None => return $crate::serve_common::client_error("status_not_ready"),
Some(key) => key,
}
};
}
pub fn get_master_key() -> Option<SecBytes> {
let startup_rw_lock = STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error");
match &*startup_rw_lock {
None => None,
Some(k) => match &k.master_key {
None => None,
Some(k) => {
let k = &*k.read();
Some(SecBytes::with(k.len(), |buf| buf.copy_from_slice(k)))
}
},
}
}
pub fn byte_to_multi_view_map(bytes: &[u8], with_value: bool) -> Map<String, Value> {
let v = if with_value {
MultipleViewValue::from(bytes)
} else {
MultipleViewValue::from_without_value(bytes)
};
let mut map = Map::new();
if let Some(v) = &v.value {
map.insert("value".to_string(), Value::String(v.to_string()));
}
if let Some(v) = &v.value_hex {
map.insert("value_hex".to_string(), Value::String(v.to_string()));
}
if let Some(v) = &v.value_base64 {
map.insert("value_base64".to_string(), Value::String(v.to_string()));
}
map
}
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 initiated!"),
Some(k) => {
Ok(opt_result!(db::open_db(& k.database_file), "Open db failed: {}"))
}
}
}