feat: v1.0.6, support list

This commit is contained in:
2024-12-12 23:31:57 +08:00
parent 4796b53aae
commit 660a9e305d
7 changed files with 429 additions and 146 deletions

237
Cargo.lock generated
View File

@@ -158,9 +158,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.93"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
[[package]]
name = "arc-swap"
@@ -174,7 +174,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"hermit-abi",
"libc",
"winapi",
]
@@ -278,15 +278,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.8.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
[[package]]
name = "cc"
version = "1.2.1"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
dependencies = [
"shlex",
]
@@ -299,9 +299,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -482,6 +482,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "elliptic-curve"
version = "0.13.8"
@@ -542,12 +548,12 @@ dependencies = [
[[package]]
name = "errno"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -716,9 +722,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.1"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "hashlink"
@@ -738,12 +744,6 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hex"
version = "0.4.3"
@@ -760,6 +760,15 @@ dependencies = [
"digest 0.9.0",
]
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "http"
version = "0.2.12"
@@ -849,12 +858,12 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [
"equivalent",
"hashbrown 0.15.1",
"hashbrown 0.15.2",
]
[[package]]
@@ -880,9 +889,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.13"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "jose-b64"
@@ -922,10 +931,11 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.72"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
dependencies = [
"once_cell",
"wasm-bindgen",
]
@@ -940,9 +950,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.164"
version = "0.2.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
[[package]]
name = "libm"
@@ -997,7 +1007,7 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "local-mini-kms"
version = "1.0.5"
version = "1.0.6"
dependencies = [
"aes-gcm-stream",
"aes-kw",
@@ -1010,9 +1020,9 @@ dependencies = [
"lazy_static",
"log",
"log4rs",
"pinentry-util",
"procfs",
"rand",
"rpassword",
"rsa",
"rusqlite",
"rust_util",
@@ -1098,6 +1108,12 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
@@ -1109,16 +1125,25 @@ dependencies = [
[[package]]
name = "mio"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"hermit-abi 0.3.9",
"libc",
"wasi",
"windows-sys 0.52.0",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-bigint-dig"
version = "0.8.4"
@@ -1248,6 +1273,12 @@ dependencies = [
"base64ct",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
version = "0.2.15"
@@ -1260,6 +1291,32 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pinentry"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ecb857a7b11a03e8872c704d0a1ae1efc20533b3be98338008527a1928ffa6"
dependencies = [
"log",
"nom",
"percent-encoding",
"secrecy",
"which",
"zeroize",
]
[[package]]
name = "pinentry-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4273c4b215a6b01462534af2a3254dea0031bf95e3731a05d5f1d17287b3ebcd"
dependencies = [
"pinentry",
"rpassword",
"secrecy",
"zeroize",
]
[[package]]
name = "pkcs1"
version = "0.7.5"
@@ -1403,9 +1460,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.7"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
"bitflags 2.6.0",
]
@@ -1463,9 +1520,9 @@ dependencies = [
[[package]]
name = "rsa"
version = "0.9.6"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519"
dependencies = [
"const-oid",
"digest 0.10.7",
@@ -1550,17 +1607,17 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.41"
version = "0.38.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
dependencies = [
"bitflags 2.6.0",
"errno 0.3.9",
"errno 0.3.10",
"itoa",
"libc",
"linux-raw-sys 0.4.14",
"once_cell",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -1612,16 +1669,25 @@ dependencies = [
"anyhow",
"cfg-if",
"libc",
"rustix 0.38.41",
"rustix 0.38.42",
"thiserror",
"windows",
]
[[package]]
name = "serde"
version = "1.0.215"
name = "secrecy"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
dependencies = [
"zeroize",
]
[[package]]
name = "serde"
version = "1.0.216"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
dependencies = [
"serde_derive",
]
@@ -1638,13 +1704,13 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.215"
version = "1.0.216"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@@ -1749,9 +1815,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.7"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
dependencies = [
"libc",
"windows-sys 0.52.0",
@@ -1819,9 +1885,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.89"
version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote 1.0.37",
@@ -1875,7 +1941,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@@ -1890,9 +1956,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.41.1"
version = "1.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
dependencies = [
"backtrace",
"bytes",
@@ -1914,14 +1980,14 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
name = "tokio-util"
version = "0.7.12"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
dependencies = [
"bytes",
"futures-core",
@@ -1938,9 +2004,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
version = "0.1.40"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-core",
@@ -1948,9 +2014,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.32"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
]
@@ -2054,9 +2120,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.95"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
dependencies = [
"cfg-if",
"once_cell",
@@ -2065,24 +2131,23 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
dependencies = [
"quote 1.0.37",
"wasm-bindgen-macro-support",
@@ -2090,22 +2155,34 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix 0.38.42",
]
[[package]]
name = "winapi"
@@ -2169,7 +2246,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@@ -2180,7 +2257,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@@ -2465,7 +2542,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@@ -2486,5 +2563,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote 1.0.37",
"syn 2.0.89",
"syn 2.0.90",
]

View File

@@ -1,6 +1,6 @@
[package]
name = "local-mini-kms"
version = "1.0.5"
version = "1.0.6"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -28,7 +28,6 @@ hyper = { version = "0.14", features = ["client", "server", "tcp", "http1", "htt
# use bundled fix musl build core dump on CentOS 6.9
rusqlite = { version = "0.32", features = ["bundled"] }
yubico_manager = { version = "0.9", optional = true }
rpassword = "7.3"
rand = "0.8"
rsa = "0.9"
aes-kw = { version = "0.2", features = ["alloc"] }
@@ -38,6 +37,7 @@ jose-jwk = "0.1"
log = "0.4"
env_logger = "0.11"
log4rs = "1.3"
pinentry-util = "0.1.1"
[target.'cfg(target_os = "linux")'.dependencies]
procfs = { version = "0.13", optional = true }

View File

@@ -103,6 +103,10 @@ xh POST http://127.0.0.1:5567/datakey \
comment='this is a test key 01'
```
```shell
xh POST http://127.0.0.1:5567/list type=value name=name limit:=10
```
| Key | Comment |
|------------------|------------------------------------------------------|
| type | `aes` |

View File

@@ -9,6 +9,11 @@ pub struct Key {
pub comment: Option<String>,
}
pub struct Keys {
pub count: usize,
pub keys: Vec<Key>,
}
pub fn make_value_key_name(name: &str) -> String {
format!("value:{}", name)
}
@@ -123,6 +128,48 @@ pub fn update_key(conn: &Connection, key: &Key) -> XResult<()> {
Ok(())
}
pub fn list_keys(conn: &Connection, ty: &str, search: &str, limit: usize) -> XResult<Keys> {
let name = format!("{}:%{}%", ty, search);
let mut count_stmt = conn.prepare("SELECT count(*) FROM keys WHERE name like ?1")?;
let mut count_iter = count_stmt.query_map(params![name], |row| {
let count: usize = row.get(0)?;
Ok(count)
})?;
let count = match count_iter.next() {
None => 0,
Some(Ok(count)) => count,
Some(Err(e)) => return simple_error!("List keys failed: {}", e),
};
log::debug!("found {} keys via: {}, limit: {}", count, name, limit);
let mut keys = vec![];
if count > 0 {
let mut list_stmt =
conn.prepare("SELECT id, name, value, comment FROM keys WHERE name like ?1 LIMIT ?2")?;
let mut list_iter = list_stmt.query_map(params![name, limit], |row| {
Ok(Key {
name: row.get(1)?,
encrypted_key: row.get(2)?,
comment: row.get(3)?,
})
})?;
loop {
match list_iter.next() {
None => {
break;
}
Some(Ok(r)) => {
log::debug!("found key name={}", r.name);
keys.push(r);
}
Some(Err(e)) => return simple_error!("List keys failed: {}", e),
}
}
}
Ok(Keys { count, keys })
}
pub fn find_key(conn: &Connection, name: &str) -> XResult<Option<Key>> {
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| {

View File

@@ -28,16 +28,55 @@ lazy_static::lazy_static! {
pub struct CommandImpl;
impl Command for CommandImpl {
fn name(&self) -> &str { "serve" }
fn name(&self) -> &str {
"serve"
}
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("Local mini KMS serve")
.arg(Arg::with_name("listen").long("listen").short("L").takes_value(true).default_value("127.0.0.1:5567").help("Listen"))
.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"))
SubCommand::with_name(self.name())
.about("Local mini KMS serve")
.arg(
Arg::with_name("listen")
.long("listen")
.short("L")
.takes_value(true)
.default_value("127.0.0.1:5567")
.help("Listen"),
)
.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 {
@@ -48,7 +87,9 @@ impl Command for CommandImpl {
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");
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"),
Ok(false) => failure_and_exit!("SHOULD NOT HAPPEN, server already init"),
@@ -59,9 +100,13 @@ impl Command for CommandImpl {
#[cfg(feature = "yubikey")]
init_with_yubikey_challenge(&rt, sub_arg_matches);
let listen = sub_arg_matches.value_of("listen").expect("Get argument listen error");
let listen = sub_arg_matches
.value_of("listen")
.expect("Get argument listen error");
rt.block_on(async {
let addr = listen.parse().unwrap_or_else(|_| panic!("Parse listen error: {}", listen));
let addr = listen
.parse()
.unwrap_or_else(|_| panic!("Parse listen error: {}", listen));
let client = Client::new();
let new_service = make_service_fn(move |conn: &AddrStream| {
let remote_addr = conn.remote_addr();
@@ -94,7 +139,12 @@ async fn response_requests(
let request_idx = GLOBAL_REQUEST_COUNT.fetch_add(1, Ordering::Relaxed);
let process = proc::get_process(remote_addr.port());
match process {
None => log::info!("[{:06}] Receive request: {}, from: {}", request_idx, req.uri(), remote_addr ),
None => log::info!(
"[{:06}] Receive request: {}, from: {}",
request_idx,
req.uri(),
remote_addr
),
Some(process) => log::info!(
"[{:06}] Receive request: {}, from: {}, process: {} {} {:?}",
request_idx,
@@ -110,17 +160,22 @@ async fn response_requests(
(&Method::POST, "/update") => update().await,
(&Method::POST, "/decrypt") => serve_encrypt_decrypt::decrypt(req).await,
(&Method::POST, "/encrypt") => serve_encrypt_decrypt::encrypt(req).await,
(&Method::POST, "/list") => serve_read_write::list(req).await,
(&Method::POST, "/read") => serve_read_write::read(req).await,
(&Method::POST, "/write") => serve_read_write::write(req).await,
(&Method::POST, "/datakey") => serve_datakey::generate(req).await,
(&Method::GET, "/status") => serve_status::status().await,
(&Method::GET, "/version") => get_version().await,
(&Method::GET, "/") => get_root().await,
_ => Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(format!("{}\n", serde_json::to_string_pretty(&json!({
"error": "not_found",
}))?).into())?),
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND).body(
format!(
"{}\n",
serde_json::to_string_pretty(&json!({
"error": "not_found",
}))?
)
.into(),
)?),
}
}
@@ -130,7 +185,9 @@ fn init_instance(db: &str) -> XResult<bool> {
let conn = db::open_db(db)?;
db::init_db(&conn)?;
let mut startup_rw_lock = serve_common::STATUP_RW_LOCK.lock().expect("Lock write startup rw lock error");
let mut startup_rw_lock = serve_common::STATUP_RW_LOCK
.lock()
.expect("Lock write startup rw lock error");
match &*startup_rw_lock {
Some(_) => Ok(false),
None => {
@@ -146,7 +203,9 @@ fn init_instance(db: &str) -> XResult<bool> {
}
fn update_instance_rsa_key_pair() -> XResult<bool> {
let mut startup_rw_lock = serve_common::STATUP_RW_LOCK.lock().expect("Lock write startup rw lock error");
let mut startup_rw_lock = serve_common::STATUP_RW_LOCK
.lock()
.expect("Lock write startup rw lock error");
match &mut *startup_rw_lock {
Some(k) => {
k.instance_rsa_key_pair = jose::generate_rsa_key(4096)?;
@@ -162,21 +221,30 @@ async fn update() -> Result<Response<Body>> {
async fn inner_update() -> XResult<(StatusCode, Value)> {
let update = update_instance_rsa_key_pair()?;
Ok((StatusCode::OK, json!({
"update": update,
})))
Ok((
StatusCode::OK,
json!({
"update": update,
}),
))
}
async fn get_version() -> Result<Response<Body>> {
Ok(Response::builder().body(format!(
"{} - {}\n", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")
).into())?)
Ok(Response::builder().body(
format!(
"{} - {}\n",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
)
.into(),
)?)
}
async fn get_root() -> Result<Response<Body>> {
if std::env::var("LOCAL_MINI_KMS_HELP").is_ok() {
Ok(Response::builder().body(format!(
r##"{} - {}
Ok(Response::builder().body(
format!(
r##"{} - {}
Supports commands:
- GET /version
- GET /status
@@ -186,8 +254,12 @@ Supports commands:
- POST /decrypt
- POST /read
- POST /write
"##, env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")
).into())?)
"##,
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
)
.into(),
)?)
} else {
Ok(Response::builder().body("Root Not Found\n".into())?)
}
@@ -195,29 +267,37 @@ Supports commands:
#[cfg(feature = "yubikey")]
fn init_with_yubikey_challenge(rt: &Runtime, sub_arg_matches: &ArgMatches) {
let mut yubikey_challenge = sub_arg_matches.value_of("yubikey-challenge").map(ToString::to_string);
let mut yubikey_challenge = sub_arg_matches
.value_of("yubikey-challenge")
.map(ToString::to_string);
let init_encrypted_master_key = sub_arg_matches.value_of("init-encrypted-master-key");
if init_encrypted_master_key.is_some() && yubikey_challenge.is_none() {
yubikey_challenge = rpassword::prompt_password("Yubikey challenge: ").ok();
yubikey_challenge =
pinentry_util::read_pin(Some("Input yubikey challenge"), Some("Challenge: "))
.ok()
.map(|p| p.get_pin().to_string());
}
let (challenge_key, init_encrypted_master_key) = match (yubikey_challenge, init_encrypted_master_key) {
(Some(yubikey_challenge), Some(init_encrypted_master_key)) => {
match yubikey_hmac::yubikey_challenge_as_32_bytes(yubikey_challenge.as_bytes()) {
Err(e) => {
warning!("Yubikey challenge failed: {}", e);
return;
let (challenge_key, init_encrypted_master_key) =
match (yubikey_challenge, init_encrypted_master_key) {
(Some(yubikey_challenge), Some(init_encrypted_master_key)) => {
match yubikey_hmac::yubikey_challenge_as_32_bytes(yubikey_challenge.as_bytes()) {
Err(e) => {
warning!("Yubikey challenge failed: {}", e);
return;
}
Ok(challenge_key) => (challenge_key, init_encrypted_master_key),
}
Ok(challenge_key) => (challenge_key, init_encrypted_master_key),
}
}
(Some(_), None) | (None, Some(_)) => {
warning!("Arguments yubikey-challenge and init-encrypted-master-key should both assigned.");
return;
}
_ => return,
};
(Some(_), None) | (None, Some(_)) => {
warning!(
"Arguments yubikey-challenge and init-encrypted-master-key should both assigned."
);
return;
}
_ => return,
};
match jose::deserialize_jwe_aes(init_encrypted_master_key, &challenge_key) {
Err(e) => warning!("Yubikey seal master key failed: {}", e),
@@ -229,7 +309,8 @@ fn init_with_yubikey_challenge(rt: &Runtime, sub_arg_matches: &ArgMatches) {
clear_master_key_hex: Some(hex::encode(&key)),
clear_master_key_base64: None,
encrypted_master_key: None,
}).await
})
.await
});
match init_master_key_result {
Err(e) => warning!("Init master key failed: {}", e),

View File

@@ -6,7 +6,14 @@ use hyper::body::Buf;
use hyper::{Body, Request, Response, StatusCode};
use rust_util::XResult;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use serde_json::{json, Map, Value};
#[derive(Serialize, Deserialize)]
struct KeysQuery {
r#type: Option<String>,
name: Option<String>,
limit: Option<usize>,
}
#[derive(Serialize, Deserialize)]
struct Named {
@@ -21,6 +28,34 @@ struct NamedValue {
comment: Option<String>,
}
pub async fn list(req: Request<Body>) -> Result<Response<Body>> {
do_response!(inner_list(req).await)
}
async fn inner_list(req: Request<Body>) -> XResult<(StatusCode, Value)> {
let whole_body = hyper::body::aggregate(req).await?;
let keys_query: KeysQuery = serde_json::from_reader(whole_body.reader())?;
let conn = open_local_db()?;
let keys = db::list_keys(
&conn,
keys_query.r#type.as_deref().unwrap_or("%"),
keys_query.name.as_deref().unwrap_or(""),
keys_query.limit.unwrap_or(10),
)?;
let mut map = Map::new();
map.insert("count".to_string(), keys.count.into());
let keys = Value::Array(
keys.keys
.iter()
.map(|k| k.name.to_string().into())
.collect(),
);
map.insert("keys".to_string(), keys);
serve_common::ok(Value::Object(map))
}
pub async fn read(req: Request<Body>) -> Result<Response<Body>> {
do_response!(inner_read(req).await)
}

View File

@@ -8,18 +8,46 @@ 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 name(&self) -> &str {
"yubikey-init-master-key"
}
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("Local mini KMS init by Yubikey(HMAC)")
.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"))
SubCommand::with_name(self.name())
.about("Local mini KMS init by Yubikey(HMAC)")
.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 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");
@@ -29,12 +57,18 @@ impl Command for CommandImpl {
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: {}")
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: {}")
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));
success!(
"Clear master key generated: {}",
hex::encode(clear_master_key)
);
clear_master_key.to_vec()
};
@@ -42,19 +76,24 @@ impl Command for CommandImpl {
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,
let yubikey_challenge = yubikey_challenge_opt.unwrap_or_else(|| {
match pinentry_util::read_pin(Some("Input yubikey challenge"), Some("Challenge: ")) {
Ok(yubikey_challenge) => yubikey_challenge.get_pin().to_string(),
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: {}");
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: {}");
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))
}
}
}