feat: v0.3.5, add subcommand yubikey-init-master-key
This commit is contained in:
28
Cargo.lock
generated
28
Cargo.lock
generated
@@ -56,12 +56,6 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "allocator-api2"
|
|
||||||
version = "0.2.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -385,9 +379,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-iterator"
|
name = "fallible-iterator"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-streaming-iterator"
|
name = "fallible-streaming-iterator"
|
||||||
@@ -518,14 +512,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"allocator-api2",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashlink"
|
name = "hashlink"
|
||||||
version = "0.8.4"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
|
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
@@ -715,9 +708,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.25.2"
|
version = "0.28.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa"
|
checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
@@ -749,7 +742,7 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "local-mini-kms"
|
name = "local-mini-kms"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -758,6 +751,7 @@ dependencies = [
|
|||||||
"josekit",
|
"josekit",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"procfs",
|
"procfs",
|
||||||
|
"rand",
|
||||||
"rpassword",
|
"rpassword",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"rust_util",
|
"rust_util",
|
||||||
@@ -1131,11 +1125,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.28.0"
|
version = "0.31.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a"
|
checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.6.0",
|
||||||
"fallible-iterator",
|
"fallible-iterator",
|
||||||
"fallible-streaming-iterator",
|
"fallible-streaming-iterator",
|
||||||
"hashlink",
|
"hashlink",
|
||||||
|
|||||||
15
Cargo.toml
15
Cargo.toml
@@ -1,17 +1,17 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "local-mini-kms"
|
name = "local-mini-kms"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
zeroize = "1.5"
|
zeroize = "1.8"
|
||||||
clap = "2.33"
|
clap = "2.34"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
base64 = "0.21"
|
base64 = "0.21"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.5"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
@@ -19,11 +19,12 @@ josekit = "0.8"
|
|||||||
secmem-proc = "0.3"
|
secmem-proc = "0.3"
|
||||||
seckey = "0.12"
|
seckey = "0.12"
|
||||||
rust_util = { version = "0.6", features = ["use_clap"] }
|
rust_util = { version = "0.6", features = ["use_clap"] }
|
||||||
tokio = { version = "1.19", features = ["full"] }
|
tokio = { version = "1.37", features = ["full"] }
|
||||||
hyper = { version = "0.14", features = ["client", "server", "tcp", "http1", "http2"] }
|
hyper = { version = "0.14", features = ["client", "server", "tcp", "http1", "http2"] }
|
||||||
rusqlite = "0.28"
|
rusqlite = "0.31"
|
||||||
yubico_manager = "0.9"
|
yubico_manager = "0.9"
|
||||||
rpassword = "7.2"
|
rpassword = "7.3"
|
||||||
|
rand = "0.8"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
procfs = "0.13"
|
procfs = "0.13"
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -2,8 +2,21 @@
|
|||||||
|
|
||||||
Mini-KMS runs local written by Rust
|
Mini-KMS runs local written by Rust
|
||||||
|
|
||||||
|
## Generate Yubikey encrypted master key
|
||||||
|
|
||||||
|
Generate encrypted master key with Yubikey:
|
||||||
|
```shell
|
||||||
|
local-mini-kms yubikey-init-master-key --generate-key [--yubikey-challenge *challenge*]
|
||||||
|
```
|
||||||
|
|
||||||
## Startup Server
|
## Startup Server
|
||||||
|
|
||||||
|
Startup without init:
|
||||||
|
```shell
|
||||||
|
local-mini-kms serve
|
||||||
|
```
|
||||||
|
|
||||||
|
Init with Yubikey:
|
||||||
```shell
|
```shell
|
||||||
local-mini-kms serve [--init-encrypted-master-key LKMS:*** [--yubikey-challenge *challenge*]]
|
local-mini-kms serve [--init-encrypted-master-key LKMS:*** [--yubikey-challenge *challenge*]]
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ mod serve_status;
|
|||||||
mod serve_init;
|
mod serve_init;
|
||||||
mod serve_encrypt_decrypt;
|
mod serve_encrypt_decrypt;
|
||||||
mod serve_read_write;
|
mod serve_read_write;
|
||||||
|
mod yubikey_init_master_key;
|
||||||
|
|
||||||
pub struct DefaultCommandImpl;
|
pub struct DefaultCommandImpl;
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ fn inner_main() -> CommandError {
|
|||||||
let commands: Vec<Box<dyn Command>> = vec![
|
let commands: Vec<Box<dyn Command>> = vec![
|
||||||
Box::new(cli::CommandImpl),
|
Box::new(cli::CommandImpl),
|
||||||
Box::new(serve::CommandImpl),
|
Box::new(serve::CommandImpl),
|
||||||
|
Box::new(yubikey_init_master_key::CommandImpl),
|
||||||
];
|
];
|
||||||
let mut app = App::new(env!("CARGO_PKG_NAME"))
|
let mut app = App::new(env!("CARGO_PKG_NAME"))
|
||||||
.version(env!("CARGO_PKG_VERSION"))
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
|||||||
60
src/yubikey_init_master_key.rs
Normal file
60
src/yubikey_init_master_key.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
use crate::{jose, yubikey_hmac};
|
||||||
|
use base64::engine::general_purpose::STANDARD;
|
||||||
|
use base64::Engine;
|
||||||
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||||
|
use rand::random;
|
||||||
|
use rust_util::util_clap::{Command, CommandError};
|
||||||
|
use rust_util::{failure_and_exit, opt_result, success};
|
||||||
|
pub struct CommandImpl;
|
||||||
|
|
||||||
|
impl Command for CommandImpl {
|
||||||
|
fn name(&self) -> &str { "yubikey-init-master-key" }
|
||||||
|
|
||||||
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
|
SubCommand::with_name(self.name()).about("Local mini KMS init yubikey")
|
||||||
|
.arg(Arg::with_name("yubikey-challenge").long("yubikey-challenge").short("c").takes_value(true).help("Yubikey challenge"))
|
||||||
|
.arg(Arg::with_name("key-hex").long("key-hex").short("x").takes_value(true).help("Key(hex), for encrypt"))
|
||||||
|
.arg(Arg::with_name("key-base64").long("key-base64").short("b").takes_value(true).help("Key(base64), for encrypt"))
|
||||||
|
.arg(Arg::with_name("generate-key").long("generate-key").short("K").help("Generate key"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||||
|
let yubikey_challenge_opt = sub_arg_matches.value_of("yubikey-challenge").map(ToString::to_string);
|
||||||
|
|
||||||
|
let hex_value_opt = sub_arg_matches.value_of("key-hex");
|
||||||
|
let base64_value_opt = sub_arg_matches.value_of("key-base64");
|
||||||
|
let generate_key_present = sub_arg_matches.is_present("generate-key");
|
||||||
|
|
||||||
|
if hex_value_opt.is_none() && base64_value_opt.is_none() && !generate_key_present {
|
||||||
|
failure_and_exit!("--key-hex, --key-base64 or --generate-key must assign one");
|
||||||
|
}
|
||||||
|
let clear_master_key = if let Some(hex_value) = hex_value_opt {
|
||||||
|
opt_result!( hex::decode(hex_value), "Decode key-hex failed: {}")
|
||||||
|
} else if let Some(base64_value) = base64_value_opt {
|
||||||
|
opt_result!(STANDARD.decode(base64_value), "Decode key-base64 failed: {}")
|
||||||
|
} else {
|
||||||
|
let clear_master_key: [u8; 32] = random();
|
||||||
|
success!("Clear master key generated: {}", hex::encode(&clear_master_key));
|
||||||
|
clear_master_key.to_vec()
|
||||||
|
};
|
||||||
|
|
||||||
|
if clear_master_key.len() != 32 {
|
||||||
|
failure_and_exit!("Master key must be 32 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
let yubikey_challenge = yubikey_challenge_opt.unwrap_or_else(
|
||||||
|
|| match rpassword::prompt_password("Yubikey challenge: ") {
|
||||||
|
Ok(yubikey_challenge) => yubikey_challenge,
|
||||||
|
Err(e) => failure_and_exit!("Read yubikey challenge failed: {}", e),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let challenge_key = opt_result!(
|
||||||
|
yubikey_hmac::yubikey_challenge_as_32_bytes(yubikey_challenge.as_bytes()), "Yubikey challenge failed: {}");
|
||||||
|
|
||||||
|
let encrypted_master_key = opt_result!(jose::serialize_jwe_aes(&clear_master_key, &challenge_key), "Encrypt master key failed: {}");
|
||||||
|
success!("Encrypted master key: {}", encrypted_master_key);
|
||||||
|
|
||||||
|
Ok(Some(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user