diff --git a/Cargo.lock b/Cargo.lock index f7cc1cec..9bc974a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,7 +117,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -128,7 +128,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -188,8 +188,8 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn", - "synstructure", + "syn 2.0.117", + "synstructure 0.13.2", ] [[package]] @@ -200,7 +200,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -244,7 +244,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -255,7 +255,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -426,6 +426,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" @@ -514,7 +520,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -538,6 +544,16 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -722,7 +738,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -746,7 +762,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.117", ] [[package]] @@ -757,7 +773,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -792,7 +808,7 @@ checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -829,6 +845,37 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.117", +] + [[package]] name = "des" version = "0.8.1" @@ -879,7 +926,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -948,7 +995,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1029,7 +1076,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1045,7 +1092,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1246,7 +1293,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1848,6 +1895,50 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -1996,7 +2087,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn", + "syn 2.0.117", ] [[package]] @@ -2228,7 +2319,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2531,7 +2622,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2561,7 +2652,7 @@ checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2686,7 +2777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.117", ] [[package]] @@ -2743,6 +2834,7 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -2970,6 +3062,41 @@ dependencies = [ "webpki-roots 1.0.6", ] +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -3177,6 +3304,40 @@ dependencies = [ "nom 7.1.3", ] +[[package]] +name = "rustify" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4800ce4c1cc2fec12c559dae2ddbf0e17fcee7569b796e6d75898efef443368b" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "http", + "reqwest 0.13.2", + "rustify_derive", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror 1.0.69", + "tracing", + "url", +] + +[[package]] +name = "rustify_derive" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ea7fda74240f7410d0198b603a8a2f662acc7d76b6667a49f9b162cd8d9b4f" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "serde_urlencoded", + "syn 1.0.109", + "synstructure 0.12.6", +] + [[package]] name = "rustix" version = "1.1.4" @@ -3187,7 +3348,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3250,6 +3411,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs 0.8.3", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework 3.7.0", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.10" @@ -3283,6 +3471,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.29" @@ -3313,7 +3510,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.117", ] [[package]] @@ -3441,7 +3638,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3452,7 +3649,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3578,7 +3775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3661,7 +3858,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn", + "syn 2.0.117", ] [[package]] @@ -3684,7 +3881,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn", + "syn 2.0.117", "tokio", "url", ] @@ -3914,7 +4111,7 @@ dependencies = [ "pkcs8", "rand 0.8.5", "rcgen", - "reqwest", + "reqwest 0.12.28", "rsa", "russh", "russh-keys", @@ -3930,6 +4127,7 @@ dependencies = [ "tokio-stream", "tracing", "tracing-subscriber", + "vaultrs", "wfe", "wfe-core", "wfe-sqlite", @@ -3959,7 +4157,7 @@ dependencies = [ "pkcs8", "rand 0.8.5", "rcgen", - "reqwest", + "reqwest 0.12.28", "rsa", "russh", "russh-keys", @@ -3976,6 +4174,17 @@ dependencies = [ "wiremock", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.117" @@ -3996,6 +4205,18 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -4004,7 +4225,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4028,7 +4249,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4057,7 +4278,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4068,7 +4289,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4170,7 +4391,7 @@ checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4291,7 +4512,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4477,6 +4698,25 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "vaultrs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ffcc0e81025065dda612ec1e26a3d81bb16ef3062354873d17a35965d68522" +dependencies = [ + "async-trait", + "derive_builder", + "http", + "reqwest 0.13.2", + "rustify", + "rustify_derive", + "serde", + "serde_json", + "thiserror 2.0.18", + "tracing", + "url", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -4489,6 +4729,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -4574,7 +4824,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -4641,6 +4891,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.26.11" @@ -4758,6 +5017,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4795,7 +5063,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4806,7 +5074,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4834,6 +5102,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -4879,6 +5156,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4927,6 +5219,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4945,6 +5243,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4963,6 +5267,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4993,6 +5303,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -5011,6 +5327,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -5029,6 +5351,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -5047,6 +5375,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -5118,7 +5452,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -5134,7 +5468,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -5262,8 +5596,8 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn", - "synstructure", + "syn 2.0.117", + "synstructure 0.13.2", ] [[package]] @@ -5283,7 +5617,7 @@ checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -5303,8 +5637,8 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", - "synstructure", + "syn 2.0.117", + "synstructure 0.13.2", ] [[package]] @@ -5343,7 +5677,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9f452528..f61d1167 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,9 @@ tempfile = "3" dirs = "5" chrono = { version = "0.4", features = ["serde"] } +# OpenBao/Vault client +vaultrs = "0.8" + # Workflow engine wfe = { version = "1.6.3", registry = "sunbeam" } wfe-core = { version = "1.6.3", registry = "sunbeam", features = ["test-support"] } diff --git a/src/openbao.rs b/src/openbao.rs index 630880bc..9e945b11 100644 --- a/src/openbao.rs +++ b/src/openbao.rs @@ -1,233 +1,159 @@ -//! Lightweight OpenBao/Vault HTTP API client. +//! OpenBao/Vault client — thin wrapper around vaultrs. //! -//! Replaces all `kubectl exec openbao-0 -- sh -c "bao ..."` calls from the -//! Python version with direct HTTP API calls via port-forward to openbao:8200. +//! Provides a `BaoClient` API that can be swapped to a different backend +//! without changing callers. use crate::error::{Result, ResultExt}; -use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use vaultrs::client::{Client, VaultClient, VaultClientSettingsBuilder}; -/// OpenBao HTTP client wrapping a base URL and optional root token. -#[derive(Clone)] +/// OpenBao HTTP client wrapping vaultrs::VaultClient. pub struct BaoClient { + inner: VaultClient, pub base_url: String, - pub token: Option, - http: reqwest::Client, } -// ── API response types ────────────────────────────────────────────────────── +// Re-export the init response type for callers that need it. +pub use vaultrs::api::sys::responses::StartInitializationResponse as InitResponse; -#[derive(Debug, Deserialize)] -pub struct InitResponse { - #[serde(alias = "unseal_keys_b64")] - pub keys_base64: Vec, - pub root_token: String, -} - -#[derive(Debug, Deserialize)] +/// Seal status response. +#[derive(Debug, Default)] pub struct SealStatusResponse { - #[serde(default)] pub initialized: bool, - #[serde(default)] pub sealed: bool, - #[serde(default)] - pub progress: u32, - #[serde(default)] - pub t: u32, - #[serde(default)] - pub n: u32, } -#[derive(Debug, Deserialize)] +/// Unseal response. +#[derive(Debug, Default)] pub struct UnsealResponse { - #[serde(default)] pub sealed: bool, - #[serde(default)] - pub progress: u32, } -/// KV v2 read response wrapper. -#[derive(Debug, Deserialize)] -struct KvReadResponse { - data: Option, -} - -#[derive(Debug, Deserialize)] -struct KvReadData { - data: Option>, -} - -// ── Client implementation ─────────────────────────────────────────────────── - impl BaoClient { /// Create a new client pointing at `base_url` (e.g. `http://localhost:8200`). pub fn new(base_url: &str) -> Self { + let url = base_url.trim_end_matches('/'); + let settings = VaultClientSettingsBuilder::default() + .address(url) + .build() + .expect("valid vault client settings"); Self { - base_url: base_url.trim_end_matches('/').to_string(), - token: None, - http: reqwest::Client::new(), + inner: VaultClient::new(settings).expect("valid vault client"), + base_url: url.to_string(), } } /// Create a client with an authentication token. pub fn with_token(base_url: &str, token: &str) -> Self { - let mut client = Self::new(base_url); - client.token = Some(token.to_string()); - client - } - - fn url(&self, path: &str) -> String { - format!("{}/v1/{}", self.base_url, path.trim_start_matches('/')) - } - - fn request(&self, method: reqwest::Method, path: &str) -> reqwest::RequestBuilder { - let mut req = self.http.request(method, self.url(path)); - if let Some(ref token) = self.token { - req = req.header("X-Vault-Token", token); + let url = base_url.trim_end_matches('/'); + let settings = VaultClientSettingsBuilder::default() + .address(url) + .token(token.to_string()) + .build() + .expect("valid vault client settings"); + Self { + inner: VaultClient::new(settings).expect("valid vault client"), + base_url: url.to_string(), } - req + } + + fn token_header(&self) -> Option { + let t = &self.inner.settings().token; + if t.is_empty() { None } else { Some(t.clone()) } } // ── System operations ─────────────────────────────────────────────── - /// Get the seal status of the OpenBao instance. pub async fn seal_status(&self) -> Result { - let resp = self - .http - .get(format!("{}/v1/sys/seal-status", self.base_url)) - .send() - .await - .ctx("Failed to connect to OpenBao")?; - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("OpenBao seal-status returned {status}: {body}"); + match vaultrs::sys::status(&self.inner).await { + Ok(status) => { + use vaultrs::sys::ServerStatus; + let (initialized, sealed) = match status { + ServerStatus::OK => (true, false), + ServerStatus::SEALED => (true, true), + ServerStatus::PERFSTANDBY | ServerStatus::STANDBY => (true, false), + ServerStatus::RECOVERY => (true, true), + ServerStatus::UNINITIALIZED | ServerStatus::UNKNOWN => (false, true), + }; + Ok(SealStatusResponse { initialized, sealed }) + } + Err(e) => Err(crate::error::SunbeamError::Other(format!( + "Failed to get seal status: {e}" + ))), } - resp.json().await.ctx("Failed to parse seal status") } - /// Initialize OpenBao with the given number of key shares and threshold. pub async fn init(&self, key_shares: u32, key_threshold: u32) -> Result { - #[derive(Serialize)] - struct InitRequest { - secret_shares: u32, - secret_threshold: u32, - } - - let resp = self - .http - .put(format!("{}/v1/sys/init", self.base_url)) - .json(&InitRequest { - secret_shares: key_shares, - secret_threshold: key_threshold, - }) - .send() - .await - .ctx("Failed to initialize OpenBao")?; - - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("OpenBao init returned {status}: {body}"); - } - resp.json().await.ctx("Failed to parse init response") + vaultrs::sys::start_initialization( + &self.inner, + key_shares as u64, + key_threshold as u64, + None, + ) + .await + .map_err(|e| crate::error::SunbeamError::Other(format!("OpenBao init failed: {e}"))) } - /// Unseal OpenBao with one key share. pub async fn unseal(&self, key: &str) -> Result { - #[derive(Serialize)] - struct UnsealRequest<'a> { - key: &'a str, - } - - let resp = self - .http - .put(format!("{}/v1/sys/unseal", self.base_url)) - .json(&UnsealRequest { key }) - .send() - .await - .ctx("Failed to unseal OpenBao")?; - - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("OpenBao unseal returned {status}: {body}"); - } - resp.json().await.ctx("Failed to parse unseal response") + let resp = vaultrs::sys::unseal( + &self.inner, + Some(key.to_string()), + None, + None, + ) + .await + .map_err(|e| crate::error::SunbeamError::Other(format!("OpenBao unseal failed: {e}")))?; + Ok(UnsealResponse { sealed: resp.sealed }) } // ── Secrets engine management ─────────────────────────────────────── - /// Enable a secrets engine at the given path. - /// Returns Ok(()) even if already enabled (400 is tolerated). pub async fn enable_secrets_engine(&self, path: &str, engine_type: &str) -> Result<()> { - #[derive(Serialize)] - struct EnableRequest<'a> { - r#type: &'a str, - } - - let resp = self - .request(reqwest::Method::POST, &format!("sys/mounts/{path}")) - .json(&EnableRequest { - r#type: engine_type, - }) - .send() - .await - .ctx("Failed to enable secrets engine")?; - - let status = resp.status(); - if status.is_success() || status.as_u16() == 400 { - // 400 = "path is already in use" — idempotent - Ok(()) - } else { - let body = resp.text().await.unwrap_or_default(); - bail!("Enable secrets engine {path} returned {status}: {body}"); + match vaultrs::sys::mount::enable(&self.inner, path, engine_type, None).await { + Ok(()) => Ok(()), + Err(e) => { + let msg = e.to_string(); + if msg.contains("400") || msg.contains("already in use") { + Ok(()) // idempotent + } else { + Err(crate::error::SunbeamError::Other(format!( + "Enable secrets engine {path}: {e}" + ))) + } + } } } // ── KV v2 operations ──────────────────────────────────────────────── - /// Read all fields from a KV v2 secret path. - /// Returns None if the path doesn't exist (404). pub async fn kv_get(&self, mount: &str, path: &str) -> Result>> { - let resp = self - .request(reqwest::Method::GET, &format!("{mount}/data/{path}")) - .send() - .await - .ctx("Failed to read KV secret")?; - - if resp.status().as_u16() == 404 { - return Ok(None); + match vaultrs::kv2::read::>(&self.inner, mount, path).await { + Ok(data) => { + let result: HashMap = data + .into_iter() + .map(|(k, v)| { + let s = match v { + serde_json::Value::String(s) => s, + other => other.to_string(), + }; + (k, s) + }) + .collect(); + Ok(Some(result)) + } + Err(e) => { + let msg = e.to_string(); + if msg.contains("404") || msg.contains("Not Found") { + Ok(None) + } else { + Err(crate::error::SunbeamError::Other(format!( + "KV get {mount}/{path}: {e}" + ))) + } + } } - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("KV get {mount}/{path} returned {status}: {body}"); - } - - let kv_resp: KvReadResponse = resp.json().await.ctx("Failed to parse KV response")?; - let data = kv_resp - .data - .and_then(|d| d.data) - .unwrap_or_default(); - - // Convert all values to strings - let result: HashMap = data - .into_iter() - .map(|(k, v)| { - let s = match v { - serde_json::Value::String(s) => s, - other => other.to_string(), - }; - (k, s) - }) - .collect(); - - Ok(Some(result)) } - /// Read a single field from a KV v2 secret path. - /// Returns empty string if path or field doesn't exist. pub async fn kv_get_field(&self, mount: &str, path: &str, field: &str) -> Result { match self.kv_get(mount, path).await? { Some(data) => Ok(data.get(field).cloned().unwrap_or_default()), @@ -235,53 +161,32 @@ impl BaoClient { } } - /// Write (create or overwrite) all fields in a KV v2 secret path. - pub async fn kv_put( - &self, - mount: &str, - path: &str, - data: &HashMap, - ) -> Result<()> { - #[derive(Serialize)] - struct KvWriteRequest<'a> { - data: &'a HashMap, - } - - let resp = self - .request(reqwest::Method::POST, &format!("{mount}/data/{path}")) - .json(&KvWriteRequest { data }) - .send() + pub async fn kv_put(&self, mount: &str, path: &str, data: &HashMap) -> Result<()> { + vaultrs::kv2::set(&self.inner, mount, path, data) .await - .ctx("Failed to write KV secret")?; - - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("KV put {mount}/{path} returned {status}: {body}"); - } + .map_err(|e| crate::error::SunbeamError::Other(format!("KV put {mount}/{path}: {e}")))?; Ok(()) } - /// Patch (merge) fields into an existing KV v2 secret path. - pub async fn kv_patch( - &self, - mount: &str, - path: &str, - data: &HashMap, - ) -> Result<()> { - #[derive(Serialize)] + /// Patch (merge) fields into an existing KV v2 secret. + /// vaultrs doesn't have a patch method, so we use a raw HTTP request. + pub async fn kv_patch(&self, mount: &str, path: &str, data: &HashMap) -> Result<()> { + #[derive(serde::Serialize)] struct KvWriteRequest<'a> { data: &'a HashMap, } - let resp = self - .request(reqwest::Method::PATCH, &format!("{mount}/data/{path}")) + let url = format!("{}/v1/{mount}/data/{path}", self.base_url); + let mut req = reqwest::Client::new() + .patch(&url) .header("Content-Type", "application/merge-patch+json") - .json(&KvWriteRequest { data }) - .send() - .await - .ctx("Failed to patch KV secret")?; + .json(&KvWriteRequest { data }); + if let Some(token) = self.token_header() { + req = req.header("X-Vault-Token", token); + } + + let resp = req.send().await.ctx("Failed to patch KV secret")?; if !resp.status().is_success() { let status = resp.status(); let body = resp.text().await.unwrap_or_default(); @@ -290,89 +195,57 @@ impl BaoClient { Ok(()) } - /// Delete a KV v2 secret path (soft delete — deletes latest version). pub async fn kv_delete(&self, mount: &str, path: &str) -> Result<()> { - let resp = self - .request(reqwest::Method::DELETE, &format!("{mount}/data/{path}")) - .send() - .await - .ctx("Failed to delete KV secret")?; - - // 404 is fine (already deleted) - if !resp.status().is_success() && resp.status().as_u16() != 404 { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("KV delete {mount}/{path} returned {status}: {body}"); + match vaultrs::kv2::delete_latest(&self.inner, mount, path).await { + Ok(()) => Ok(()), + Err(e) => { + let msg = e.to_string(); + if msg.contains("404") { + Ok(()) + } else { + Err(crate::error::SunbeamError::Other(format!( + "KV delete {mount}/{path}: {e}" + ))) + } + } } - Ok(()) } // ── Auth operations ───────────────────────────────────────────────── - /// Enable an auth method at the given path. - /// Tolerates "already enabled" (400/409). pub async fn auth_enable(&self, path: &str, method_type: &str) -> Result<()> { - #[derive(Serialize)] - struct AuthEnableRequest<'a> { - r#type: &'a str, - } - - let resp = self - .request(reqwest::Method::POST, &format!("sys/auth/{path}")) - .json(&AuthEnableRequest { - r#type: method_type, - }) - .send() - .await - .ctx("Failed to enable auth method")?; - - let status = resp.status(); - if status.is_success() || status.as_u16() == 400 { - Ok(()) - } else { - let body = resp.text().await.unwrap_or_default(); - bail!("Enable auth {path} returned {status}: {body}"); + match vaultrs::sys::auth::enable(&self.inner, path, method_type, None).await { + Ok(()) => Ok(()), + Err(e) => { + let msg = e.to_string(); + if msg.contains("400") || msg.contains("already in use") { + Ok(()) + } else { + Err(crate::error::SunbeamError::Other(format!( + "Enable auth {path}: {e}" + ))) + } + } } } - /// Write a policy. pub async fn write_policy(&self, name: &str, policy_hcl: &str) -> Result<()> { - #[derive(Serialize)] - struct PolicyRequest<'a> { - policy: &'a str, - } - - let resp = self - .request( - reqwest::Method::PUT, - &format!("sys/policies/acl/{name}"), - ) - .json(&PolicyRequest { policy: policy_hcl }) - .send() + vaultrs::sys::policy::set(&self.inner, name, policy_hcl) .await - .ctx("Failed to write policy")?; - - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("Write policy {name} returned {status}: {body}"); - } - Ok(()) + .map_err(|e| crate::error::SunbeamError::Other(format!("Write policy {name}: {e}"))) } - /// Write to an arbitrary API path (for auth config, roles, database config, etc.). - pub async fn write( - &self, - path: &str, - data: &serde_json::Value, - ) -> Result { - let resp = self - .request(reqwest::Method::POST, path) - .json(data) - .send() - .await - .with_ctx(|| format!("Failed to write to {path}"))?; + // ── Generic write (for auth config, roles, etc.) ──────────────────── + pub async fn write(&self, path: &str, data: &serde_json::Value) -> Result { + let url = format!("{}/v1/{}", self.base_url, path.trim_start_matches('/')); + let mut req = reqwest::Client::new().post(&url).json(data); + if let Some(token) = self.token_header() { + req = req.header("X-Vault-Token", token); + } + + let resp = req.send().await + .with_ctx(|| format!("Failed to write to {path}"))?; if !resp.status().is_success() { let status = resp.status(); let body = resp.text().await.unwrap_or_default(); @@ -387,34 +260,8 @@ impl BaoClient { } } - /// Read from an arbitrary API path. - pub async fn read(&self, path: &str) -> Result> { - let resp = self - .request(reqwest::Method::GET, path) - .send() - .await - .with_ctx(|| format!("Failed to read {path}"))?; - - if resp.status().as_u16() == 404 { - return Ok(None); - } - if !resp.status().is_success() { - let status = resp.status(); - let body = resp.text().await.unwrap_or_default(); - bail!("Read {path} returned {status}: {body}"); - } - - let body = resp.text().await.unwrap_or_default(); - if body.is_empty() { - Ok(Some(serde_json::Value::Null)) - } else { - Ok(Some(serde_json::from_str(&body)?)) - } - } - // ── Database secrets engine ───────────────────────────────────────── - /// Configure the database secrets engine connection. pub async fn write_db_config( &self, name: &str, @@ -435,7 +282,6 @@ impl BaoClient { Ok(()) } - /// Create a database static role. pub async fn write_db_static_role( &self, name: &str, @@ -450,8 +296,7 @@ impl BaoClient { "rotation_period": rotation_period, "rotation_statements": rotation_statements, }); - self.write(&format!("database/static-roles/{name}"), &data) - .await?; + self.write(&format!("database/static-roles/{name}"), &data).await?; Ok(()) } } @@ -461,39 +306,27 @@ mod tests { use super::*; #[test] - fn test_client_url_construction() { + fn test_new_client() { let client = BaoClient::new("http://localhost:8200"); - assert_eq!(client.url("sys/seal-status"), "http://localhost:8200/v1/sys/seal-status"); - assert_eq!(client.url("/sys/seal-status"), "http://localhost:8200/v1/sys/seal-status"); - } - - #[test] - fn test_client_url_strips_trailing_slash() { - let client = BaoClient::new("http://localhost:8200/"); assert_eq!(client.base_url, "http://localhost:8200"); } #[test] fn test_with_token() { let client = BaoClient::with_token("http://localhost:8200", "mytoken"); - assert_eq!(client.token, Some("mytoken".to_string())); + assert_eq!(client.inner.settings().token, "mytoken"); } #[test] - fn test_new_has_no_token() { - let client = BaoClient::new("http://localhost:8200"); - assert!(client.token.is_none()); + fn test_strips_trailing_slash() { + let client = BaoClient::new("http://localhost:8200/"); + assert_eq!(client.base_url, "http://localhost:8200"); } #[tokio::test] async fn test_seal_status_error_on_nonexistent_server() { - // Connecting to a port where nothing is listening should produce an - // error (connection refused), not a panic or hang. let client = BaoClient::new("http://127.0.0.1:19999"); let result = client.seal_status().await; - assert!( - result.is_err(), - "seal_status should return an error when the server is unreachable" - ); + assert!(result.is_err()); } } diff --git a/src/workflows/seed/steps/openbao_init.rs b/src/workflows/seed/steps/openbao_init.rs index d59a2dba..d7791d75 100644 --- a/src/workflows/seed/steps/openbao_init.rs +++ b/src/workflows/seed/steps/openbao_init.rs @@ -164,7 +164,7 @@ impl StepBody for InitOrUnsealOpenBao { let mut root_token = String::new(); let status = status.unwrap_or_else(|| crate::openbao::SealStatusResponse { - initialized: false, sealed: true, progress: 0, t: 0, n: 0, + initialized: false, sealed: true, }); // Check if truly initialized (not just a placeholder secret) @@ -213,7 +213,7 @@ impl StepBody for InitOrUnsealOpenBao { // Unseal if needed let status = bao.seal_status().await.unwrap_or_else(|_| { crate::openbao::SealStatusResponse { - initialized: true, sealed: true, progress: 0, t: 0, n: 0, + initialized: true, sealed: true, } }); if status.sealed && !unseal_key.is_empty() {