diff --git a/Cargo.lock b/Cargo.lock index 59b345b..ba71884 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -741,7 +741,7 @@ checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "local-mini-kms" -version = "0.3.1" +version = "0.3.2" dependencies = [ "base64", "clap", diff --git a/Cargo.toml b/Cargo.toml index 47e9fd4..acaf80e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "local-mini-kms" -version = "0.3.1" +version = "0.3.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index d246c64..b91d0f3 100644 --- a/README.md +++ b/README.md @@ -54,3 +54,8 @@ curl -X POST http://127.0.0.1:5567/read \ -d '{"name":"test"}' ``` +Upgrade to v3.2 +```sql +ALTER TABLE keys ADD COLUMN comment TEXT; +``` + diff --git a/src/cli.rs b/src/cli.rs index 214d634..0c31b68 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -32,6 +32,7 @@ impl Command for CommandImpl { .arg(Arg::with_name("value-hex").long("value-hex").short("x").takes_value(true).help("Value(hex), for encrypt")) .arg(Arg::with_name("value-base64").long("value-base64").short("b").takes_value(true).help("Value(base64), for encrypt")) .arg(Arg::with_name("yubikey-challenge").long("yubikey-challenge").short("c").takes_value(true).help("Yubikey challenge")) + .arg(Arg::with_name("comment").long("comment").takes_value(true).help("Comment")) .arg(Arg::with_name("force-write").long("force-write").short("F").help("Force write value")) } @@ -151,12 +152,14 @@ async fn do_write(_arg_matches: &ArgMatches<'_>, sub_arg_matches: &ArgMatches<'_ let value_hex = sub_arg_matches.value_of("value-hex"); let value_base64 = sub_arg_matches.value_of("value-base64"); let force_write = sub_arg_matches.is_present("force-write"); + let comment = sub_arg_matches.value_of("comment"); + let body = if let Some(value) = value { - json!({ "name": key, "force_write": force_write, "value": json!({"value": value}) }) + json!({ "name": key, "force_write": force_write, "comment": comment, "value": json!({"value": value}) }) } else if let Some(value_hex) = value_hex { - json!({ "name": key, "force_write": force_write, "value": json!({"value_hex": value_hex}) }) + json!({ "name": key, "force_write": force_write, "comment": comment, "value": json!({"value_hex": value_hex}) }) } else if let Some(value_base64) = value_base64 { - json!({ "name": key, "force_write": force_write, "value": json!({"value_base64": value_base64}) }) + json!({ "name": key, "force_write": force_write, "comment": comment, "value": json!({"value_base64": value_base64}) }) } else { return simple_error!("Require one of value, value-hex, value-base64"); }; diff --git a/src/db.rs b/src/db.rs index bdcda8a..311b5a2 100644 --- a/src/db.rs +++ b/src/db.rs @@ -6,6 +6,7 @@ pub const DEFAULT_MASTER_KEY_VERIFICATION_KEY: &'static str = "__master_verifica pub struct Key { pub name: String, pub encrypted_key: String, + pub comment: Option, } pub fn make_db_key_name(name: &str) -> String { @@ -19,7 +20,8 @@ pub fn open_db(db: &str) -> XResult { } pub fn init_db(conn: &Connection) -> XResult { - let mut stmt = conn.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='keys'")?; + let mut stmt = conn.prepare( + "SELECT name FROM sqlite_master WHERE type='table' AND name='keys'")?; let mut rows = stmt.query(())?; if rows.next()?.is_some() { information!("Table keys exists, skip init"); @@ -30,7 +32,8 @@ pub fn init_db(conn: &Connection) -> XResult { CREATE TABLE keys ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, - value TEXT + value TEXT, + comment TEXT ) "##, ())?; success!("Table keys created"); @@ -38,27 +41,36 @@ pub fn init_db(conn: &Connection) -> XResult { } pub fn insert_key(conn: &Connection, key: &Key) -> XResult<()> { + let default_comment = "".to_string(); let _ = conn.execute( - "INSERT INTO keys (name, value) VALUES (?1, ?2)", - (&key.name, &key.encrypted_key), + "INSERT INTO keys (name, value, comment) VALUES (?1, ?2, ?3)", + (&key.name, &key.encrypted_key, key.comment.as_ref().unwrap_or_else(|| &default_comment)), )?; Ok(()) } pub fn update_key(conn: &Connection, key: &Key) -> XResult<()> { - let _ = conn.execute( - "UPDATE keys SET value = ?1 WHERE name = ?2", - (&key.encrypted_key, &key.name), - )?; + if let Some(comment) = &key.comment { + let _ = conn.execute( + "UPDATE keys SET value = ?1, comment = ?2 WHERE name = ?3", + (&key.encrypted_key, comment, &key.name), + )?; + } else { + let _ = conn.execute( + "UPDATE keys SET value = ?1 WHERE name = ?2", + (&key.encrypted_key, &key.name), + )?; + } Ok(()) } pub fn find_key(conn: &Connection, name: &str) -> XResult> { - let mut stmt = conn.prepare("SELECT id, name, value FROM keys WHERE name = ?1")?; + let mut stmt = conn.prepare("SELECT id, name, value, comment FROM keys WHERE name = ?1")?; let mut key_iter = stmt.query_map(params![name], |row| { Ok(Key { name: row.get(1)?, encrypted_key: row.get(2)?, + comment: Some(row.get(3)?), }) })?; match key_iter.next() { diff --git a/src/serve_init.rs b/src/serve_init.rs index 3efedb6..2324743 100644 --- a/src/serve_init.rs +++ b/src/serve_init.rs @@ -71,6 +71,7 @@ pub async fn inner_init_request(init_request: InitRequest) -> XResult<(StatusCod let key = Key { name: db::DEFAULT_MASTER_KEY_VERIFICATION_KEY.to_string(), encrypted_key: jose::serialize_jwe_aes("LOCAL-MINI-KMS:MAGIC-VERIFICATION-KEY".as_bytes(), &clear_master_key)?, + comment: None, }; db::insert_key(&conn, &key)?; } diff --git a/src/serve_read_write.rs b/src/serve_read_write.rs index 320565c..9a8ce0c 100644 --- a/src/serve_read_write.rs +++ b/src/serve_read_write.rs @@ -19,6 +19,7 @@ struct NamedValue { name: String, force_write: Option, value: MultipleViewValue, + comment: Option, } pub async fn read(req: Request) -> Result> { @@ -86,6 +87,7 @@ async fn inner_write(req: Request) -> XResult<(StatusCode, Value)> { let new_db_key = Key { name: db_key_name, encrypted_key: encrypt_value.clone(), + comment: named_value.comment, }; let response_body = if let Some(db_key) = db_key {