From 6b8668eaf16f6679af003626041e1b587448c9f5 Mon Sep 17 00:00:00 2001 From: Gordon Wang <36049150+gordonwang0@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:30:29 -0700 Subject: [PATCH] Update auth server template with API version (#62) ## Purpose - Updates the custom auth server template with versioning support by adding `api-version` as a query parameter - Updates to hyper 1.2 and clap 4, with required refactor - Updates and removes outdated documentation ## Does this introduce a breaking change? ``` [x] Yes [ ] No ``` The new query parameter `api-version` is required for custom authentication requests. ## Pull Request Type What kind of change does this Pull Request introduce? ``` [ ] Bugfix [x] Feature [ ] Code style update (formatting, local variables) [x] Refactoring (no functional changes, no api changes) [x] Documentation content changes [ ] Other... Please describe: ``` --- samples/auth-server-template/Cargo.lock | 818 ++++++++---------- samples/auth-server-template/Cargo.toml | 8 +- samples/auth-server-template/Dockerfile | 2 +- samples/auth-server-template/README.md | 30 +- .../{api.yaml => api/0.5.0.yaml} | 32 +- .../deploy/auth-server-template.yaml | 2 +- .../auth-server-template/src/authenticate.rs | 65 +- samples/auth-server-template/src/http.rs | 104 ++- samples/auth-server-template/src/incoming.rs | 138 --- samples/auth-server-template/src/main.rs | 134 ++- 10 files changed, 615 insertions(+), 718 deletions(-) rename samples/auth-server-template/{api.yaml => api/0.5.0.yaml} (83%) delete mode 100644 samples/auth-server-template/src/incoming.rs diff --git a/samples/auth-server-template/Cargo.lock b/samples/auth-server-template/Cargo.lock index 2c15149..9abf444 100644 --- a/samples/auth-server-template/Cargo.lock +++ b/samples/auth-server-template/Cargo.lock @@ -2,6 +2,27 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -12,23 +33,51 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", ] [[package]] @@ -36,14 +85,16 @@ name = "auth-server-template" version = "0.1.0" dependencies = [ "chrono", + "clap", "futures", "futures-core", "futures-util", + "http-body-util", "hyper", + "hyper-util", "openssl", "serde", "serde_json", - "structopt", "tokio", "tokio-openssl", ] @@ -54,29 +105,44 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" -version = "1.3.2" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" [[package]] name = "cfg-if" @@ -86,93 +152,69 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", - "time", "wasm-bindgen", - "winapi", + "windows-targets 0.52.4", ] [[package]] name = "clap" -version = "2.34.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", + "clap_builder", + "clap_derive", ] [[package]] -name = "codespan-reporting" -version = "0.11.1" +name = "clap_builder" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ - "termcolor", - "unicode-width", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "core-foundation-sys" -version = "0.8.4" +name = "clap_derive" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", + "heck", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "cxx-build" -version = "1.0.94" +name = "clap_lex" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] -name = "cxxbridge-flags" -version = "1.0.94" +name = "colorchoice" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] -name = "cxxbridge-macro" -version = "1.0.94" +name = "core-foundation-sys" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "fnv" @@ -197,9 +239,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -212,9 +254,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -222,15 +264,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -239,38 +281,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -285,37 +327,28 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.3.3" +name = "gimli" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "http" -version = "0.2.9" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -324,12 +357,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", "pin-project-lite", ] @@ -341,19 +386,18 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.26" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -361,140 +405,141 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", "socket2", "tokio", - "tower-service", - "tracing", - "want", ] [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "libc" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "libc" -version = "0.2.144" +name = "log" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] -name = "link-cplusplus" -version = "1.0.8" +name = "memchr" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] -name = "log" -version = "0.4.17" +name = "miniz_oxide" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ - "cfg-if", + "adler", ] -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - [[package]] name = "mio" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "wasi", + "windows-sys 0.48.0", ] [[package]] -name = "num-integer" -version = "0.1.45" +name = "num-traits" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", - "num-traits", ] [[package]] -name = "num-traits" -version = "0.2.15" +name = "num_cpus" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "autocfg", + "hermit-abi", + "libc", ] [[package]] -name = "num_cpus" -version = "1.15.0" +name = "object" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ - "hermit-abi 0.2.6", - "libc", + "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags", "cfg-if", @@ -513,14 +558,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn", ] [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" dependencies = [ "cc", "libc", @@ -530,9 +575,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -542,89 +587,65 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.27" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] -name = "ryu" -version = "1.0.13" +name = "rustc-demangle" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] -name = "scratch" -version = "1.0.5" +name = "ryu" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "serde" -version = "1.0.162" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.162" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -633,111 +654,53 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "libc", - "winapi", + "autocfg", ] [[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" +name = "smallvec" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] -name = "structopt-derive" -version = "0.4.18" +name = "socket2" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "syn" -version = "1.0.109" +name = "strsim" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "syn" -version = "2.0.15" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "tokio" -version = "1.28.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ - "autocfg", + "backtrace", "libc", "mio", "num_cpus", @@ -749,20 +712,20 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn", ] [[package]] name = "tokio-openssl" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08f9ffb7809f1b20c1b398d92acf4cc719874b3b2b2d9ea2f09b4a80350878a" +checksum = "6ffab79df67727f6acf57f1ff743091873c24c579b1e2ce4d8f53e47ded4d63d" dependencies = [ "futures-util", "openssl", @@ -770,55 +733,17 @@ dependencies = [ "tokio", ] -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-segmentation" -version = "1.10.1" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "vcpkg" @@ -826,34 +751,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -862,9 +759,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -872,24 +769,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -897,191 +794,160 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.52.4", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.48.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.52.4", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 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", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" diff --git a/samples/auth-server-template/Cargo.toml b/samples/auth-server-template/Cargo.toml index efe8d05..5f0fdee 100644 --- a/samples/auth-server-template/Cargo.toml +++ b/samples/auth-server-template/Cargo.toml @@ -5,13 +5,15 @@ edition = "2021" [dependencies] chrono = "0.4" +clap = { version = "4", features = ["derive"] } futures = "0.3" futures-core = "0.3" futures-util = "0.3" -hyper = { version = "0.14", features = ["http1", "server", "tcp"] } +http-body-util = "0.1" +hyper = { version = "1.2", features = ["http1", "server"] } +hyper-util = { version = "0.1", features = ["tokio"] } openssl = "0.10" -structopt = "0.3" serde = { version = "1", features = ["derive"] } serde_json = "1" -tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1", features = ["macros", "net", "rt-multi-thread"] } tokio-openssl = "0.6" diff --git a/samples/auth-server-template/Dockerfile b/samples/auth-server-template/Dockerfile index 7459882..168f384 100644 --- a/samples/auth-server-template/Dockerfile +++ b/samples/auth-server-template/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.17 +FROM alpine:3.19 RUN apk upgrade --no-cache && \ apk add --no-cache libgcc diff --git a/samples/auth-server-template/README.md b/samples/auth-server-template/README.md index 58a9202..43f8387 100644 --- a/samples/auth-server-template/README.md +++ b/samples/auth-server-template/README.md @@ -1,12 +1,12 @@ # auth-server-template -This is a sample server for Azure IoT MQ broker custom authentication. +This is a sample server for Azure IoT MQ broker custom authentication. -The custom authentication feature of the IoT MQ MQTT brokers provides an extension point that allows customers to plug in an authentication server to authenticate clients that connect to the MQTT broker. The server here is intended as a sample for how such a custom authentication can be implemented. +The custom authentication feature of the IoT MQ broker provides an extension point that allows customers to plug in an authentication server to authenticate clients that connect to the MQTT broker. The server here is intended as a sample for how such a custom authentication can be implemented. ## Deploying the template -A private preview image of the template is available with the tag `e4kpreview.azurecr.io/auth-server-template:latest`. You only need to deploy the template yourself once you make modifications. +A private preview image of the template is available with the tag `ghcr.io/azure-samples/explore-iot-operations/auth-server-template:0.5.0`. You only need to deploy the template yourself once you make modifications. The template server needs to be built and deployed as a Kubernetes service. You will need to provide the repository for hosting its container image. @@ -36,19 +36,27 @@ kubectl apply -f ./deploy/auth-server-template.yaml ## Using the template -Add the custom authentication method to your IoT MQ BrokerAuthentication resource. An example of the fields to add is below: +Add an MQ BrokerAuthentication with custom authentication. An example BrokerAuthentication is below: ```yaml -authenticationMethods: - - custom:; +apiVersion: mq.iotoperations.azure.com/v1beta1 +kind: BrokerAuthentication +metadata: + name: custom-authn +spec: + listenerRef: + - listener + authenticationMethods: + - method: custom # Required, must match the pod name in auth-server-template.yaml endpoint: https://auth-server-template - # Required, as this template uses a self-signed CA. - ca_cert: custom-auth-ca # Optional; this example uses the client cert generated by make_credentials.sh auth: - x509: - secretName: custom-auth-client-cert + type: x509 + source: k8s + secret: custom-auth-client-cert + # Required, as this template uses a self-signed CA. + ca_cert: custom-auth-ca ``` -The auth server template will approve authentication requests from all clients, except clients providing usernames that start with `deny`. +The auth server template will approve authentication requests from all clients, except clients providing usernames that start with `deny`. It will set a credential expiration of 10 seconds for any clients providing usernames that start with `expire`. diff --git a/samples/auth-server-template/api.yaml b/samples/auth-server-template/api/0.5.0.yaml similarity index 83% rename from samples/auth-server-template/api.yaml rename to samples/auth-server-template/api/0.5.0.yaml index f5df12f..5c285d2 100644 --- a/samples/auth-server-template/api.yaml +++ b/samples/auth-server-template/api/0.5.0.yaml @@ -1,13 +1,11 @@ openapi: 3.0.3 info: - title: IoT MQ Custom Authentication API + title: Azure IoT Operations MQ Custom Authentication API description: |- This is the HTTP API used for custom authentication. Custom authentication allows you to extend client authentication beyond the provided authentication methods. With custom authentication, the IoT MQ broker will forward the credentials of connecting clients to an external custom authentication server. The custom authentication server will decide whether to accept clients and determine each client's authorization attributes. The IoT MQ broker will make requests to the custom authentication server with the formats specified below. Likewise, the custom authentication server must respond with the specified response format. - - This API is currently in preview, and may change before GA. - version: preview + version: 0.5.0 servers: - url: https://custom-auth-endpoint/ description: User-specified endpoint @@ -23,6 +21,14 @@ paths: operationId: authClient description: |- This request from the IoT MQ broker to the custom authentication server forwards the connecting client's credentials to the custom authentication server. The custom authentication server must then use the provided information to accept or reject the client. + parameters: + - in: query + name: api-version + description: API version of custom authentication API + schema: + type: string + example: "0.5.0" + required: true requestBody: description: |- Request from the IoT MQ broker to the custom authentication server. The request body contains the information from either an MQTT CONNECT or AUTH packet. @@ -73,6 +79,12 @@ paths: text/plain: schema: $ref: '#/components/schemas/ErrorResponse' + 422: + description: Unprocessable content in request. Returned when the custom authentication API version in the request is unsupported by the server. The response body will contain the server's supported API versions. + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedVersionResponse' components: schemas: AuthRequest: @@ -143,3 +155,15 @@ components: type: string description: Error message for the IoT MQ broker to log example: error message + UnsupportedVersionResponse: + type: object + description: Returned when a request's api-version is unsupported + properties: + supportedVersions: + type: array + items: + type: string + description: Supported custom authentication API versions. The MQTT broker should automatically retry with one of these versions. + example: ["0.5.0"] + required: + - supportedVersions diff --git a/samples/auth-server-template/deploy/auth-server-template.yaml b/samples/auth-server-template/deploy/auth-server-template.yaml index b1050b8..1f6ae5a 100644 --- a/samples/auth-server-template/deploy/auth-server-template.yaml +++ b/samples/auth-server-template/deploy/auth-server-template.yaml @@ -8,7 +8,7 @@ spec: containers: - name: auth-server-template # Change this if you are using your own container registry. - image: e4kpreview.azurecr.io/auth-server-template:latest + image: ghcr.io/azure-samples/explore-iot-operations/auth-server-template:0.5.0 imagePullPolicy: Always ports: - name: https diff --git a/samples/auth-server-template/src/authenticate.rs b/samples/auth-server-template/src/authenticate.rs index 7740ebb..e3da6de 100644 --- a/samples/auth-server-template/src/authenticate.rs +++ b/samples/auth-server-template/src/authenticate.rs @@ -3,30 +3,64 @@ use std::collections::BTreeMap; +use hyper::{header, Method, StatusCode}; use openssl::x509::X509; use crate::http::{ParsedRequest, Response}; +/// Returned when the client requests an invalid API version. Contains a list of +/// supported API versions. +#[derive(Debug, serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct SupportedApiVersions { + /// List of supported API versions. + supported_versions: Vec, +} + +impl Default for SupportedApiVersions { + fn default() -> Self { + SupportedApiVersions { + supported_versions: vec!["0.5.0".to_string()], + } + } +} + /// Authenticate the connecting MQTT client. pub(crate) async fn authenticate(req: ParsedRequest) -> Response { // Check that the request follows the authentication spec. - if req.method != hyper::Method::POST { + if req.method != Method::POST { return Response::method_not_allowed(&req.method); } - let body = if let Some(body) = req.body { - body - } else { + if let Some(content_type) = req.headers.get(header::CONTENT_TYPE.as_str()) { + if content_type.to_lowercase() != "application/json" { + return Response::bad_request(format!("invalid content-type: {content_type}")); + } + } + + let Some(body) = req.body else { return Response::bad_request("missing body"); }; - if req.uri != "/" { - return Response::not_found(format!("{} not found", req.uri)); + if req.path != "/" { + return Response::not_found(format!("{} not found", req.path)); + } + + if let Some(api_version) = req.query.get("api-version") { + // Currently, the custom auth API supports only version 0.5.0. + if api_version != "0.5.0" { + return Response::json( + StatusCode::UNPROCESSABLE_ENTITY, + SupportedApiVersions::default(), + ); + } + } else { + return Response::bad_request("missing api-version"); } let body: ClientAuthRequest = match serde_json::from_str(&body) { Ok(body) => body, - Err(err) => return Response::bad_request(format!("invalid client request body: {}", err)), + Err(err) => return Response::bad_request(format!("invalid client request body: {err}")), }; Response::from(auth_client(body).await) @@ -96,19 +130,22 @@ struct AuthPassResponse { impl From for Response { fn from(response: ClientAuthResponse) -> Response { match response { - ClientAuthResponse::Allow(response) => Response::json(hyper::StatusCode::OK, response), + ClientAuthResponse::Allow(response) => Response::json(StatusCode::OK, response), ClientAuthResponse::Deny { reason } => { let body = serde_json::json!({ "reason": reason, }); - Response::json(hyper::StatusCode::FORBIDDEN, body) + Response::json(StatusCode::FORBIDDEN, body) } } } } +// This implementation is a placeholder. The actual implementation may need to be async, so allow unused async +// in the signature. +#[allow(clippy::unused_async)] async fn auth_client(body: ClientAuthRequest) -> ClientAuthResponse { match body { ClientAuthRequest::Connect { @@ -118,15 +155,12 @@ async fn auth_client(body: ClientAuthRequest) -> ClientAuthResponse { } => { // TODO: Authenticate the client with provided credentials. For now, this template just logs the // credentials. Note the password is base64-encoded. - println!( - "Got MQTT CONNECT; username: {:?}, password: {:?}", - username, password - ); + println!("Got MQTT CONNECT; username: {username:?}, password: {password:?}"); // TODO: Authenticate the client with provided certs. For now, this template just logs the certs. if let Some(certs) = certs { println!("Got certs:"); - println!("{:#?}", certs); + println!("{certs:#?}"); } // TODO: Get attributes associated with the presented certificate. For now, this template @@ -139,7 +173,8 @@ async fn auth_client(body: ClientAuthRequest) -> ClientAuthResponse { // expiry and allows clients to remain connected indefinitely. let example_expiry = username.as_ref().and_then(|username| { if username.starts_with("expire") { - let example_expiry = chrono::Utc::now() + chrono::Duration::seconds(10); + let example_expiry = chrono::Utc::now() + + chrono::TimeDelta::try_seconds(10).expect("invalid hardcoded time value"); Some(example_expiry.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)) } else { diff --git a/samples/auth-server-template/src/http.rs b/samples/auth-server-template/src/http.rs index cabb17d..df09374 100644 --- a/samples/auth-server-template/src/http.rs +++ b/samples/auth-server-template/src/http.rs @@ -1,21 +1,47 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +use std::{ + collections::HashMap, + fmt::{Debug, Display, Formatter, Result as FmtResult}, +}; + +use http_body_util::{BodyExt, Full}; +use hyper::{body::Bytes, header, Method, StatusCode}; + +pub(crate) type HttpRequest = hyper::Request; +pub(crate) type HttpResponse = hyper::Response>; + pub(crate) struct ParsedRequest { - pub method: hyper::Method, + pub method: Method, pub version: String, - pub uri: String, - pub headers: std::collections::HashMap, + pub path: String, + pub query: HashMap, + pub headers: HashMap, pub body: Option, } impl ParsedRequest { - pub(crate) async fn from_http(req: hyper::Request) -> Result { + pub(crate) async fn from_http(req: HttpRequest) -> Result { let method = req.method().clone(); - let uri = req.uri().to_string(); + let uri = req.uri(); + let path = uri.path().to_string(); let version = format!("{:?}", req.version()); - let mut headers = std::collections::HashMap::with_capacity(req.headers().len()); + let mut query = HashMap::new(); + if let Some(q) = uri.query() { + let parts: Vec<&str> = q.split('&').collect(); + + for p in parts { + if let Some((key, value)) = p.split_once('=') { + query.insert(key.to_lowercase().to_string(), value.to_string()); + } else { + return Err(Response::bad_request("bad query value")); + } + } + } + + let mut headers = HashMap::with_capacity(req.headers().len()); for (key, value) in req.headers() { let key = key.to_string(); let value = value @@ -26,10 +52,12 @@ impl ParsedRequest { headers.insert(key, value); } - let body = hyper::body::to_bytes(req.into_body()) + let body = req + .into_body() + .collect() .await .map_err(|_| Response::bad_request("unable to get body"))? - .to_vec(); + .to_bytes(); let body = if body.is_empty() { None @@ -44,24 +72,29 @@ impl ParsedRequest { Ok(ParsedRequest { method, version, - uri, + path, + query, headers, body, }) } } -impl std::fmt::Debug for ParsedRequest { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Debug for ParsedRequest { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { write!(f, "\n----\n")?; - writeln!(f, "> {} {} {}", self.method, self.uri, self.version)?; + writeln!(f, "> {} {} {}", self.method, self.path, self.version)?; + + if !&self.query.is_empty() { + writeln!(f, "> query: {:?}", self.query)?; + } for (key, value) in &self.headers { - writeln!(f, "> {}: {}", key, value)?; + writeln!(f, "> {key}: {value}")?; } if let Some(body) = &self.body { - write!(f, "\n{}", body)?; + write!(f, "\n{body}")?; } Ok(()) @@ -69,67 +102,62 @@ impl std::fmt::Debug for ParsedRequest { } pub(crate) enum Response { - Error { - status: hyper::StatusCode, - message: String, - }, - - Json { - status: hyper::StatusCode, - body: String, - }, + Error { status: StatusCode, message: String }, + + Json { status: StatusCode, body: String }, } impl Response { - pub fn bad_request(message: impl std::fmt::Display) -> Self { + pub fn bad_request(message: impl Display) -> Self { Response::Error { - status: hyper::StatusCode::BAD_REQUEST, + status: StatusCode::BAD_REQUEST, message: message.to_string(), } } - pub fn not_found(message: impl std::fmt::Display) -> Self { + pub fn not_found(message: impl Display) -> Self { Response::Error { - status: hyper::StatusCode::NOT_FOUND, + status: StatusCode::NOT_FOUND, message: message.to_string(), } } - pub fn method_not_allowed(method: &hyper::Method) -> Self { + pub fn method_not_allowed(method: &Method) -> Self { Response::Error { - status: hyper::StatusCode::METHOD_NOT_ALLOWED, - message: format!("{} not allowed", method), + status: StatusCode::METHOD_NOT_ALLOWED, + message: format!("{method} not allowed"), } } - pub fn json(status: hyper::StatusCode, body: impl serde::Serialize) -> Self { + pub fn json(status: StatusCode, body: impl serde::Serialize) -> Self { let body = serde_json::to_string(&body).unwrap(); Response::Json { status, body } } #[allow(clippy::wrong_self_convention)] // This function should consume self. - pub fn to_http(self) -> hyper::Response { + pub fn to_http(self) -> HttpResponse { let mut response = hyper::Response::builder(); let (status, body, debug_body) = match self { Response::Error { status, message } => { println!(); - println!("{}", message); + println!("{message}"); - (status, hyper::Body::from(message), None) + (status, Bytes::from(message), None) } Response::Json { status, body } => { - response = response.header(hyper::header::CONTENT_TYPE, "application/json"); + response = response.header(header::CONTENT_TYPE, "application/json"); - (status, hyper::Body::from(body.clone()), Some(body)) + (status, Bytes::from(body.clone()), Some(body)) } }; println!(); - println!("< {}", status); + println!("< {status}"); + let body = Full::new(body); let response = response.status(status).body(body).unwrap(); for (key, value) in response.headers() { @@ -138,7 +166,7 @@ impl Response { if let Some(body) = debug_body { println!(); - println!("{}", body); + println!("{body}"); } response diff --git a/samples/auth-server-template/src/incoming.rs b/samples/auth-server-template/src/incoming.rs deleted file mode 100644 index 3e19769..0000000 --- a/samples/auth-server-template/src/incoming.rs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -use std::{pin::Pin, task::Poll}; - -use openssl::{ - pkey::{PKey, Private}, - ssl::{Ssl, SslAcceptor, SslMethod, SslVerifyMode}, - x509::{store::X509StoreBuilder, X509}, -}; - -type TlsStream = tokio_openssl::SslStream; - -type HandshakeFuture = - std::pin::Pin>>>; - -/// A stream of incoming TLS connections, for use with a hyper server. -pub struct Incoming { - listener: tokio::net::TcpListener, - tls_acceptor: SslAcceptor, - connections: futures_util::stream::FuturesUnordered, -} - -impl Incoming { - pub(crate) fn new( - addr: (&str, u16), - server_cert_chain: Vec, - private_key: PKey, - client_cert_issuer: Option>, - ) -> Result> { - let listener = std::net::TcpListener::bind(addr)?; - listener.set_nonblocking(true)?; - let listener = tokio::net::TcpListener::from_std(listener)?; - - let mut tls_acceptor = SslAcceptor::mozilla_modern(SslMethod::tls())?; - tls_acceptor.set_private_key(&private_key)?; - - let mut server_cert_chain = server_cert_chain.into_iter(); - - if let Some(leaf_cert) = server_cert_chain.next() { - tls_acceptor.set_certificate(&leaf_cert)?; - } else { - return Err( - std::io::Error::new(std::io::ErrorKind::InvalidInput, "no certs provided").into(), - ); - } - - if let Some(issuer) = client_cert_issuer { - let mut store = X509StoreBuilder::new()?; - - for cert in issuer { - store.add_cert(cert)?; - } - - tls_acceptor.set_verify_cert_store(store.build())?; - tls_acceptor.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT); - } - - for cert in server_cert_chain { - tls_acceptor.add_extra_chain_cert(cert)?; - } - - let tls_acceptor = tls_acceptor.build(); - - Ok(Incoming { - listener, - tls_acceptor, - connections: Default::default(), - }) - } -} - -impl hyper::server::accept::Accept for Incoming { - type Conn = TlsStream; - type Error = std::io::Error; - - fn poll_accept( - mut self: Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> Poll>> { - use futures_core::Stream; - - loop { - match self.listener.poll_accept(cx) { - Poll::Ready(Ok((stream, _))) => { - let stream = Ssl::new(self.tls_acceptor.context()) - .and_then(|ssl| tokio_openssl::SslStream::new(ssl, stream)); - let mut stream = match stream { - Ok(stream) => stream, - Err(err) => { - eprintln!( - "Dropping client that failed to complete a TLS handshake: {}", - err - ); - continue; - } - }; - self.connections.push(Box::pin(async move { - Pin::new(&mut stream).accept().await?; - Ok(stream) - })); - } - - Poll::Ready(Err(err)) => eprintln!( - "Dropping client that failed to completely establish a TCP connection: {}", - err - ), - - Poll::Pending => break, - } - } - - loop { - if self.connections.is_empty() { - return Poll::Pending; - } - - match Pin::new(&mut self.connections).poll_next(cx) { - Poll::Ready(Some(Ok(stream))) => { - println!("Accepted connection from client"); - return Poll::Ready(Some(Ok(stream))); - } - - Poll::Ready(Some(Err(err))) => eprintln!( - "Dropping client that failed to complete a TLS handshake: {}", - err - ), - - Poll::Ready(None) => { - println!("Shutting down web server"); - return Poll::Ready(None); - } - - Poll::Pending => return Poll::Pending, - } - } - } -} diff --git a/samples/auth-server-template/src/main.rs b/samples/auth-server-template/src/main.rs index 0408240..1977a52 100644 --- a/samples/auth-server-template/src/main.rs +++ b/samples/auth-server-template/src/main.rs @@ -1,44 +1,50 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#![warn(clippy::all, clippy::pedantic)] + /// Handles authentication of MQTT connections. mod authenticate; /// Handles parsing and generating HTTP requests. mod http; -/// Handles TLS and socket communication. -mod incoming; - -use std::path::PathBuf; +use std::{path::PathBuf, pin::Pin}; -use openssl::{pkey::PKey, x509::X509}; -use structopt::StructOpt; +use clap::Parser; +use hyper::server::conn::http1::Builder as ServerBuilder; +use hyper_util::rt::TokioIo; +use openssl::{ + pkey::{PKey, Private}, + ssl::{Ssl, SslAcceptor, SslContext, SslMethod, SslVerifyMode}, + x509::{store::X509StoreBuilder, X509}, +}; +use tokio_openssl::SslStream; /// Command-line options for this program. -#[derive(StructOpt)] +#[derive(Parser)] struct Options { /// Port to listen on. - #[structopt(long, short, value_name = "PORT")] + #[arg(long, short, value_name = "PORT")] port: u16, /// TLS server cert chain to present to connecting clients. - #[structopt(long, short = "c", value_name = "SERVER_CERT_CHAIN")] + #[arg(long, short = 'c', value_name = "SERVER_CERT_CHAIN")] server_cert_chain: PathBuf, /// Private key of TLS server cert. - #[structopt(long, short = "k", value_name = "SERVER_KEY")] + #[arg(long, short = 'k', value_name = "SERVER_KEY")] server_key: PathBuf, /// Optional CA certs for validating client certificates. Omit to disable /// client certificate validation. - #[structopt(long, short = "i", value_name = "CLIENT_CERT_ISSUER")] + #[arg(long, short = 'i', value_name = "CLIENT_CERT_ISSUER")] client_cert_issuer: Option, } #[tokio::main] async fn main() -> Result<(), Box> { - let options = Options::from_args(); + let options = Options::parse(); let server_key = std::fs::read(&options.server_key)?; let server_key = PKey::private_key_from_pem(&server_key)?; @@ -55,29 +61,95 @@ async fn main() -> Result<(), Box> { None }; + let tls_context = tls_context(server_cert_chain, &server_key, client_cert_issuer)?; + println!("Will listen on 0.0.0.0:{}", options.port); - let incoming = incoming::Incoming::new( - ("0.0.0.0", options.port), - server_cert_chain, - server_key, - client_cert_issuer, - )?; - - hyper::Server::builder(incoming) - .serve(hyper::service::make_service_fn(move |_| { - let service = hyper::service::service_fn(process_req); - - async move { Ok::<_, std::convert::Infallible>(service) } - })) - .await?; - - Ok(()) + let listener = std::net::TcpListener::bind(("0.0.0.0", options.port))?; + listener.set_nonblocking(true)?; + let listener = tokio::net::TcpListener::from_std(listener)?; + + loop { + let stream = match listener.accept().await { + Ok((stream, _)) => stream, + Err(err) => { + println!("Failed to accept TCP connection: {err}"); + + continue; + } + }; + + let ssl = Ssl::new(&tls_context).expect("invalid TLS context"); + let mut stream = match SslStream::new(ssl, stream) { + Ok(stream) => stream, + Err(err) => { + println!("Failed to create SSLStream: {err}"); + + continue; + } + }; + + if let Err(err) = Pin::new(&mut stream).accept().await { + println!("Failed to establish TLS connection: {err}"); + + continue; + } + + let stream = TokioIo::new(stream); + + tokio::spawn(async move { + if let Err(err) = ServerBuilder::new() + .serve_connection(stream, hyper::service::service_fn(process_req)) + .await + { + println!("HTTP server error: {err:?}"); + } + }); + } +} + +/// Create a TLS context from the given X.509 credentials. +fn tls_context( + server_cert_chain: Vec, + private_key: &PKey, + client_cert_issuer: Option>, +) -> Result> { + let mut tls_acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls())?; + tls_acceptor.set_private_key(private_key)?; + + let mut server_cert_chain = server_cert_chain.into_iter(); + + if let Some(leaf_cert) = server_cert_chain.next() { + tls_acceptor.set_certificate(&leaf_cert)?; + } else { + return Err( + std::io::Error::new(std::io::ErrorKind::InvalidInput, "no certs provided").into(), + ); + } + + if let Some(issuer) = client_cert_issuer { + let mut store = X509StoreBuilder::new()?; + + for cert in issuer { + store.add_cert(cert)?; + } + + tls_acceptor.set_verify_cert_store(store.build())?; + tls_acceptor.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT); + } + + for cert in server_cert_chain { + tls_acceptor.add_extra_chain_cert(cert)?; + } + + let tls_acceptor = tls_acceptor.build(); + + Ok(tls_acceptor.into_context()) } /// Parse an HTTP request and authenticate the connecting client. async fn process_req( - req: hyper::Request, -) -> Result, std::convert::Infallible> { + req: http::HttpRequest, +) -> Result { let req = match http::ParsedRequest::from_http(req).await { Ok(req) => req, Err(response) => return Ok(response.to_http()), @@ -85,7 +157,7 @@ async fn process_req( // This prints the incoming HTTP request. Useful for debugging, but note that // it may print sensitive data. - println!("{:?}", req); + println!("{req:?}"); let response = authenticate::authenticate(req).await;