From 0daa89a05a3c389e9129972e9b803b6b93c0688f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Thu, 14 Aug 2025 14:02:55 +0200 Subject: [PATCH 1/3] Update Tonic to 0.14 --- Cargo.lock | 265 ++++++++++-------------- Cargo.toml | 5 +- Dockerfile | 6 +- crates/defguard/Cargo.toml | 2 +- crates/defguard_core/Cargo.toml | 6 +- crates/defguard_core/build.rs | 47 ++--- crates/defguard_core/src/grpc/mod.rs | 2 +- crates/defguard_event_logger/Cargo.toml | 2 +- 8 files changed, 144 insertions(+), 191 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7ad6e4335..4cd981e739 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "arbitrary" @@ -274,40 +274,13 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "axum" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" -dependencies = [ - "async-trait", - "axum-core 0.4.5", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "itoa", - "matchit 0.7.3", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower 0.5.2", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ - "axum-core 0.5.2", + "axum-core", "bytes", "form_urlencoded", "futures-util", @@ -317,7 +290,7 @@ dependencies = [ "hyper", "hyper-util", "itoa", - "matchit 0.8.4", + "matchit", "memchr", "mime", "percent-encoding", @@ -329,7 +302,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", "tracing", @@ -341,31 +314,11 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff8ee1869817523c8f91c20bf17fd932707f66c2e7e0b0f811b29a227289562" dependencies = [ - "axum 0.8.4", + "axum", "forwarded-header-value", "serde", ] -[[package]] -name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.5.2" @@ -392,8 +345,8 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d" dependencies = [ - "axum 0.8.4", - "axum-core 0.5.2", + "axum", + "axum-core", "bytes", "cookie", "form_urlencoded", @@ -408,7 +361,7 @@ dependencies = [ "serde", "serde_html_form", "serde_path_to_error", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", ] @@ -708,9 +661,9 @@ checksum = "bba18ee93d577a8428902687bcc2b6b45a56b1981a1f6d779731c86cc4c5db18" [[package]] name = "clap" -version = "4.5.43" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f" +checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" dependencies = [ "clap_builder", "clap_derive", @@ -718,9 +671,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.43" +version = "4.5.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" dependencies = [ "anstream", "anstyle", @@ -730,9 +683,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck", "proc-macro2", @@ -1079,7 +1032,7 @@ version = "1.5.0" dependencies = [ "anyhow", "argon2", - "axum 0.8.4", + "axum", "axum-client-ip", "axum-extra", "base32", @@ -1105,7 +1058,6 @@ dependencies = [ "paste", "pgp", "prost", - "prost-build", "pulldown-cmark", "rand 0.8.5", "rand_core 0.6.4", @@ -1128,14 +1080,15 @@ dependencies = [ "strum", "strum_macros", "tera", - "thiserror 2.0.12", + "thiserror 2.0.14", "time", "tokio", "tokio-stream", "tokio-util", "tonic", - "tonic-build", "tonic-health", + "tonic-prost", + "tonic-prost-build", "totp-lite", "tower-http", "tracing", @@ -1163,7 +1116,7 @@ dependencies = [ "ipnetwork", "serde_json", "sqlx", - "thiserror 2.0.12", + "thiserror 2.0.14", "tokio", "tracing", ] @@ -1174,7 +1127,7 @@ version = "0.0.0" dependencies = [ "defguard_core", "defguard_event_logger", - "thiserror 2.0.12", + "thiserror 2.0.14", "tokio", "tracing", ] @@ -1183,7 +1136,7 @@ dependencies = [ name = "defguard_web_ui" version = "0.0.0" dependencies = [ - "axum 0.8.4", + "axum", "mime_guess", "rust-embed", ] @@ -2689,12 +2642,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "matchit" version = "0.8.4" @@ -3214,9 +3161,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a8cb46bdc156b1c90460339ae6bfd45ba0394e5effbaa640badb4987fdc261" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] name = "pbkdf2" @@ -3260,7 +3207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ "memchr", - "thiserror 2.0.12", + "thiserror 2.0.14", "ucd-trie", ] @@ -3367,7 +3314,7 @@ dependencies = [ "sha3", "signature", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.14", "twofish", "x25519-dalek", "zeroize", @@ -3536,18 +3483,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0" +checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.13.5" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" dependencies = [ "bytes", "prost-derive", @@ -3555,9 +3502,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.13.5" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" dependencies = [ "heck", "itertools 0.14.0", @@ -3568,6 +3515,8 @@ dependencies = [ "prettyplease", "prost", "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", "regex", "syn", "tempfile", @@ -3575,9 +3524,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.13.5" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", "itertools 0.14.0", @@ -3588,9 +3537,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.13.5" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" dependencies = [ "prost", ] @@ -3639,6 +3588,15 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" +[[package]] +name = "pulldown-cmark-to-cmark" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5b6a0769a491a08b31ea5c62494a8f144ee0987d86d670a8af4df1e1b7cde75" +dependencies = [ + "pulldown-cmark", +] + [[package]] name = "quinn" version = "0.11.8" @@ -3653,7 +3611,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2 0.5.10", - "thiserror 2.0.12", + "thiserror 2.0.14", "tokio", "tracing", "web-time", @@ -3674,7 +3632,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.12", + "thiserror 2.0.14", "tinyvec", "tracing", "web-time", @@ -3849,9 +3807,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.22" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64 0.22.1", "bytes", @@ -3886,7 +3844,7 @@ dependencies = [ "tokio-native-tls", "tokio-rustls", "tokio-util", - "tower 0.5.2", + "tower", "tower-http", "tower-service", "url", @@ -4067,15 +4025,6 @@ dependencies = [ "security-framework 3.3.0", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" @@ -4490,7 +4439,7 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.12", + "thiserror 2.0.14", "time", ] @@ -4607,7 +4556,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.14", "tokio", "tokio-stream", "tracing", @@ -4691,7 +4640,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror 2.0.14", "tracing", "uuid", "whoami", @@ -4731,7 +4680,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror 2.0.14", "tracing", "uuid", "whoami", @@ -4757,7 +4706,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.12", + "thiserror 2.0.14", "tracing", "url", "uuid", @@ -4889,9 +4838,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619" dependencies = [ "proc-macro2", "quote", @@ -4985,11 +4934,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.14", ] [[package]] @@ -5005,9 +4954,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227" dependencies = [ "proc-macro2", "quote", @@ -5184,13 +5133,12 @@ dependencies = [ [[package]] name = "tonic" -version = "0.12.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +checksum = "67ac5a8627ada0968acec063a4746bf79588aa03ccb66db2f75d7dce26722a40" dependencies = [ - "async-stream", "async-trait", - "axum 0.7.9", + "axum", "base64 0.22.1", "bytes", "flate2", @@ -5203,14 +5151,13 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost", "rustls-native-certs", - "rustls-pemfile", - "socket2 0.5.10", + "socket2 0.6.0", + "sync_wrapper", "tokio", "tokio-rustls", "tokio-stream", - "tower 0.4.13", + "tower", "tower-layer", "tower-service", "tracing", @@ -5218,29 +5165,54 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.12.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" +checksum = "49e323d8bba3be30833707e36d046deabf10a35ae8ad3cae576943ea8933e25d" dependencies = [ "prettyplease", "proc-macro2", - "prost-build", - "prost-types", "quote", "syn", ] [[package]] name = "tonic-health" -version = "0.12.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eaf34ddb812120f5c601162d5429933c9b527d901ab0e7f930d3147e33a09b2" +checksum = "d8aa31379f0851de4f223496a469ffcaae24ad4ce736493179c3e42135e2af5c" dependencies = [ - "async-stream", "prost", "tokio", "tokio-stream", "tonic", + "tonic-prost", +] + +[[package]] +name = "tonic-prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c511b9a96d40cb12b7d5d00464446acf3b9105fd3ce25437cfe41c92b1c87d" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef298fcd01b15e135440c4b8c974460ceca4e6a5af7f1c933b08e4d2875efa1" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn", + "tempfile", + "tonic-build", ] [[package]] @@ -5255,26 +5227,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.5.2" @@ -5283,9 +5235,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", + "indexmap 2.10.0", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -5313,7 +5268,7 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-util", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", "tracing", @@ -5623,7 +5578,7 @@ version = "9.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d047458f1b5b65237c2f6dc6db136945667f40a7668627b3490b9513a3d43a55" dependencies = [ - "axum 0.8.4", + "axum", "base64 0.22.1", "mime_guess", "regex", @@ -5644,9 +5599,9 @@ checksum = "e2eebbbfe4093922c2b6734d7c679ebfebd704a0d7e56dfcb0d05818ce28977d" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -6509,7 +6464,7 @@ dependencies = [ "memchr", "pbkdf2", "sha1", - "thiserror 2.0.12", + "thiserror 2.0.14", "time", "xz2", "zeroize", diff --git a/Cargo.toml b/Cargo.toml index 3a5f0a6d97..dc2f5fb586 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,6 @@ md4 = "0.10" parse_link_header = "0.4" paste = "1.0.15" pgp = "0.15" -prost = "0.13" pulldown-cmark = "0.13" # match version used by sqlx rand = "0.8" @@ -89,8 +88,8 @@ tokio = { version = "1", features = [ ] } tokio-stream = "0.1" tokio-util = "0.7" -tonic = { version = "0.12", features = ["gzip", "tls-native-roots"] } -tonic-health = "0.12" +tonic = { version = "0.14", features = ["gzip", "tls-native-roots"] } +tonic-health = "0.14" totp-lite = { version = "2.0" } tower-http = { version = "0.6", features = ["fs", "trace"] } tracing = "0.1" diff --git a/Dockerfile b/Dockerfile index bb8956d83e..8e3960e72c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM node:24-alpine AS web WORKDIR /app -COPY web/package.json web/pnpm-lock.yaml web/.npmrc . +COPY web/package.json web/pnpm-lock.yaml web/.npmrc ./ RUN npm i -g pnpm RUN pnpm install --ignore-scripts --frozen-lockfile COPY web/ . @@ -45,8 +45,8 @@ RUN cargo install --locked --bin defguard --path ./crates/defguard --root /build # run FROM debian:bookworm-slim RUN apt-get update -y && \ - apt-get install --no-install-recommends -y ca-certificates libssl-dev && \ - rm -rf /var/lib/apt/lists/* + apt-get install --no-install-recommends -y ca-certificates libssl-dev && \ + rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=builder /build/bin/defguard . ENTRYPOINT ["./defguard"] diff --git a/crates/defguard/Cargo.toml b/crates/defguard/Cargo.toml index 5c453e15fe..a6bdd11b29 100644 --- a/crates/defguard/Cargo.toml +++ b/crates/defguard/Cargo.toml @@ -15,9 +15,9 @@ defguard_event_logger = { workspace = true } # external dependencies anyhow = { workspace = true } +bytes = { workspace = true } dotenvy = "0.15" secrecy = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } -bytes = { workspace = true } tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/crates/defguard_core/Cargo.toml b/crates/defguard_core/Cargo.toml index 10bfa678c7..598dec8d44 100644 --- a/crates/defguard_core/Cargo.toml +++ b/crates/defguard_core/Cargo.toml @@ -37,7 +37,7 @@ openidconnect = { version = "4.0", default-features = false, optional = true, fe parse_link_header = { workspace = true } paste = { workspace = true } pgp = { workspace = true } -prost = { workspace = true } +prost = "0.14" pulldown-cmark = { workspace = true } # match version used by sqlx rand = { workspace = true } @@ -66,6 +66,7 @@ tokio-stream = { workspace = true } tokio-util = { workspace = true } tonic = { workspace = true } tonic-health = { workspace = true } +tonic-prost = "0.14" totp-lite = { workspace = true } tower-http = { workspace = true } tracing = { workspace = true } @@ -105,8 +106,7 @@ serde_qs = "0.13" webauthn-authenticator-rs = { version = "0.5", features = ["softpasskey"] } [build-dependencies] -prost-build = "0.13" -tonic-build = "0.12" +tonic-prost-build = "0.14" vergen-git2 = { version = "1.0", features = ["build"] } [features] diff --git a/crates/defguard_core/build.rs b/crates/defguard_core/build.rs index 79b6db8f42..a4c2030a96 100644 --- a/crates/defguard_core/build.rs +++ b/crates/defguard_core/build.rs @@ -5,30 +5,29 @@ fn main() -> Result<(), Box> { let git2 = Git2Builder::default().branch(true).sha(true).build()?; Emitter::default().add_instructions(&git2)?.emit()?; - let mut config = prost_build::Config::new(); - config.protoc_arg("--experimental_allow_proto3_optional"); - config.type_attribute( - "license.LicenseLimits", - "#[derive(serde::Serialize, serde::Deserialize)]", - ); - tonic_build::configure().compile_protos_with_config( - config, - &[ - "../../proto/core/auth.proto", - "../../proto/core/proxy.proto", - "../../proto/worker/worker.proto", - "../../proto/wireguard/gateway.proto", - "../../proto/enterprise/firewall/firewall.proto", - "src/enterprise/proto/license.proto", - ], - &[ - "../../proto/core", - "../../proto/worker", - "../../proto/wireguard", - "../../proto/enterprise/firewall", - "src/enterprise/proto", - ], - )?; + tonic_prost_build::configure() + .protoc_arg("--experimental_allow_proto3_optional") + .type_attribute( + "license.LicenseLimits", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .compile_protos( + &[ + "../../proto/core/auth.proto", + "../../proto/core/proxy.proto", + "../../proto/worker/worker.proto", + "../../proto/wireguard/gateway.proto", + "../../proto/enterprise/firewall/firewall.proto", + "src/enterprise/proto/license.proto", + ], + &[ + "../../proto/core", + "../../proto/worker", + "../../proto/wireguard", + "../../proto/enterprise/firewall", + "src/enterprise/proto", + ], + )?; println!("cargo:rerun-if-changed=../../migrations"); println!("cargo:rerun-if-changed=../../proto"); println!("cargo:rerun-if-changed=src/enterprise"); diff --git a/crates/defguard_core/src/grpc/mod.rs b/crates/defguard_core/src/grpc/mod.rs index c75c21c0d8..f2a971334f 100644 --- a/crates/defguard_core/src/grpc/mod.rs +++ b/crates/defguard_core/src/grpc/mod.rs @@ -874,7 +874,7 @@ pub async fn run_grpc_server( JwtInterceptor::new(ClaimsType::Gateway), ); - let (mut health_reporter, health_service) = tonic_health::server::health_reporter(); + let (health_reporter, health_service) = tonic_health::server::health_reporter(); health_reporter .set_serving::>() .await; diff --git a/crates/defguard_event_logger/Cargo.toml b/crates/defguard_event_logger/Cargo.toml index cafa1ccf04..48077f17e4 100644 --- a/crates/defguard_event_logger/Cargo.toml +++ b/crates/defguard_event_logger/Cargo.toml @@ -12,6 +12,7 @@ rust-version.workspace = true defguard_core = { workspace = true } # external dependencies +bytes = { workspace = true } chrono = { workspace = true } ipnetwork = { workspace = true } serde_json = { workspace = true } @@ -19,4 +20,3 @@ sqlx = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } -bytes = { workspace = true } From fc2dd27fc42e801ba6b64c0f329f1f97636d9574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Thu, 14 Aug 2025 14:18:43 +0200 Subject: [PATCH 2/3] Clippy auto fixes --- crates/defguard_core/src/db/models/user.rs | 15 ++- .../defguard_core/src/db/models/wireguard.rs | 1 + .../src/enterprise/db/models/api_tokens.rs | 1 + .../src/enterprise/db/models/snat.rs | 1 + .../enterprise/directory_sync/microsoft.rs | 59 +++++----- .../src/enterprise/grpc/desktop_client_mfa.rs | 2 +- .../src/enterprise/handlers/api_tokens.rs | 2 +- .../src/enterprise/handlers/openid_login.rs | 1 + .../enterprise/handlers/openid_providers.rs | 2 +- .../src/enterprise/ldap/client.rs | 12 +-- .../defguard_core/src/enterprise/ldap/hash.rs | 5 +- .../defguard_core/src/enterprise/ldap/mod.rs | 20 ++-- .../src/enterprise/ldap/model.rs | 6 +- .../defguard_core/src/enterprise/ldap/sync.rs | 24 +++-- .../src/enterprise/ldap/utils.rs | 30 +++--- crates/defguard_core/src/events.rs | 4 + crates/defguard_core/src/grpc/client_mfa.rs | 6 +- .../src/grpc/gateway/client_state.rs | 19 ++-- crates/defguard_core/src/grpc/gateway/mod.rs | 2 +- crates/defguard_core/src/grpc/mod.rs | 1 + .../src/handlers/activity_log.rs | 4 +- crates/defguard_core/src/handlers/auth.rs | 102 +++++++++--------- crates/defguard_core/src/handlers/group.rs | 6 +- .../src/handlers/network_devices.rs | 22 ++-- crates/defguard_core/src/handlers/user.rs | 4 +- .../defguard_core/src/handlers/wireguard.rs | 2 +- .../src/wireguard_peer_disconnect.rs | 2 +- .../defguard_event_logger/src/description.rs | 5 +- crates/defguard_event_logger/src/message.rs | 4 + crates/defguard_event_router/src/lib.rs | 37 +++---- 30 files changed, 201 insertions(+), 200 deletions(-) diff --git a/crates/defguard_core/src/db/models/user.rs b/crates/defguard_core/src/db/models/user.rs index 3896dc26b3..b29676c259 100644 --- a/crates/defguard_core/src/db/models/user.rs +++ b/crates/defguard_core/src/db/models/user.rs @@ -893,14 +893,13 @@ impl User { username_or_email: &str, ) -> Result, SqlxError> { let maybe_user = Self::find_by_username(&mut *conn, username_or_email).await?; - match maybe_user { - Some(user) => Ok(Some(user)), - None => { - debug!( - "Failed to find user by username {username_or_email}. Attempting to find by email" - ); - Ok(Self::find_by_email(&mut *conn, username_or_email).await?) - } + if let Some(user) = maybe_user { + Ok(Some(user)) + } else { + debug!( + "Failed to find user by username {username_or_email}. Attempting to find by email" + ); + Ok(Self::find_by_email(&mut *conn, username_or_email).await?) } } pub(crate) async fn find_many_by_emails<'e, E>( diff --git a/crates/defguard_core/src/db/models/wireguard.rs b/crates/defguard_core/src/db/models/wireguard.rs index 198887d0ef..67d996dd10 100644 --- a/crates/defguard_core/src/db/models/wireguard.rs +++ b/crates/defguard_core/src/db/models/wireguard.rs @@ -234,6 +234,7 @@ pub enum NetworkAddressError { } impl WireguardNetwork { + #[must_use] pub fn new( name: String, address: Vec, diff --git a/crates/defguard_core/src/enterprise/db/models/api_tokens.rs b/crates/defguard_core/src/enterprise/db/models/api_tokens.rs index 86f3d8d238..4045fd5574 100644 --- a/crates/defguard_core/src/enterprise/db/models/api_tokens.rs +++ b/crates/defguard_core/src/enterprise/db/models/api_tokens.rs @@ -15,6 +15,7 @@ pub struct ApiToken { } impl ApiToken { + #[must_use] pub fn new(user_id: Id, created_at: NaiveDateTime, name: String, token_string: &str) -> Self { let token_hash = Self::hash_token(token_string); Self { diff --git a/crates/defguard_core/src/enterprise/db/models/snat.rs b/crates/defguard_core/src/enterprise/db/models/snat.rs index 19448eed7b..e483cbb42a 100644 --- a/crates/defguard_core/src/enterprise/db/models/snat.rs +++ b/crates/defguard_core/src/enterprise/db/models/snat.rs @@ -21,6 +21,7 @@ pub struct UserSnatBinding { } impl UserSnatBinding { + #[must_use] pub fn new(user_id: Id, location_id: Id, public_ip: IpAddr) -> Self { Self { id: NoId, diff --git a/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs b/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs index 0f1044bc37..b690ea72ec 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs @@ -59,9 +59,10 @@ impl From for Vec { response .value .into_iter() - .filter_map(|group| match group.display_name { - Some(name) => Some(DirectoryGroup { id: group.id, name }), - None => { + .filter_map(|group| { + if let Some(name) = group.display_name { + Some(DirectoryGroup { id: group.id, name }) + } else { warn!( "Group with ID {} doesn't have a display name set, skipping it.", group.id @@ -177,7 +178,7 @@ impl MicrosoftDirectorySync { self.url )))?; debug!("Tenant ID extracted successfully: {tenant_id}",); - Ok(tenant_id.to_string()) + Ok((*tenant_id).to_string()) } async fn refresh_access_token(&mut self) -> Result<(), DirectorySyncError> { @@ -252,7 +253,30 @@ impl MicrosoftDirectorySync { let mut combined_response = GroupsResponse::default(); let mut url = GROUPS_URL.to_string(); - if !self.group_filter.is_empty() { + if self.group_filter.is_empty() { + debug!("No group filter defined, all groups will be synced."); + let params = vec![("$top", MAX_RESULTS)]; + let mut query = Some(params.as_slice()); + + for _ in 0..MAX_REQUESTS { + let response = make_get_request(&url, access_token, query).await?; + let response: GroupsResponse = + parse_response(response, "Failed to query Microsoft groups.").await?; + combined_response.value.extend(response.value); + + if let Some(next_page) = response.next_page { + url = next_page; + // Set `query` to `None` as the next page URL already contains query parameters from the preceding request. + query = None; + debug!("Found next page of results, querying it: {url}"); + } else { + debug!("No more pages of results found, finishing query."); + break; + } + + sleep(REQUEST_PAGINATION_SLOWDOWN).await; + } + } else { info!( "Applying defined group filter to user group query, only the following groups will be synced: {:?}", self.group_filter @@ -261,7 +285,7 @@ impl MicrosoftDirectorySync { let groups = self .group_filter .iter() - .map(|group| group.replace("'", "''")) + .map(|group| group.replace('\'', "''")) .collect::>(); // Microsoft has a limit of about 15 OR conditions per request, so batch it first. @@ -284,29 +308,6 @@ impl MicrosoftDirectorySync { parse_response(response, "Failed to query Microsoft groups.").await?; combined_response.value.extend(response.value); - sleep(REQUEST_PAGINATION_SLOWDOWN).await; - } - } else { - debug!("No group filter defined, all groups will be synced."); - let params = vec![("$top", MAX_RESULTS)]; - let mut query = Some(params.as_slice()); - - for _ in 0..MAX_REQUESTS { - let response = make_get_request(&url, access_token, query).await?; - let response: GroupsResponse = - parse_response(response, "Failed to query Microsoft groups.").await?; - combined_response.value.extend(response.value); - - if let Some(next_page) = response.next_page { - url = next_page; - // Set `query` to `None` as the next page URL already contains query parameters from the preceding request. - query = None; - debug!("Found next page of results, querying it: {url}"); - } else { - debug!("No more pages of results found, finishing query."); - break; - } - sleep(REQUEST_PAGINATION_SLOWDOWN).await; } } diff --git a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs index f580779d5f..069d1fd86d 100644 --- a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs +++ b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs @@ -137,7 +137,7 @@ impl ClientMfaServer { })?; return Err(Status::unauthenticated("unauthorized")); } - }; + } self.sessions.insert( pubkey.clone(), diff --git a/crates/defguard_core/src/enterprise/handlers/api_tokens.rs b/crates/defguard_core/src/enterprise/handlers/api_tokens.rs index 37c2f52988..d76a3488ea 100644 --- a/crates/defguard_core/src/enterprise/handlers/api_tokens.rs +++ b/crates/defguard_core/src/enterprise/handlers/api_tokens.rs @@ -90,7 +90,7 @@ pub async fn fetch_api_tokens( let tokens_info: Vec = ApiToken::find_by_user_id(&appstate.pool, user.id) .await? .into_iter() - .map(|token| token.into()) + .map(Into::into) .collect(); Ok(ApiResponse { diff --git a/crates/defguard_core/src/enterprise/handlers/openid_login.rs b/crates/defguard_core/src/enterprise/handlers/openid_login.rs index 0a236218bb..8394cec32c 100644 --- a/crates/defguard_core/src/enterprise/handlers/openid_login.rs +++ b/crates/defguard_core/src/enterprise/handlers/openid_login.rs @@ -49,6 +49,7 @@ use crate::{ /// - starts with non-special character /// - only special characters allowed: . - _ /// - no whitespaces +#[must_use] pub fn prune_username(username: &str, handling: OpenidUsernameHandling) -> String { let mut result = username.to_string(); diff --git a/crates/defguard_core/src/enterprise/handlers/openid_providers.rs b/crates/defguard_core/src/enterprise/handlers/openid_providers.rs index 26e537f3b1..34a775542c 100644 --- a/crates/defguard_core/src/enterprise/handlers/openid_providers.rs +++ b/crates/defguard_core/src/enterprise/handlers/openid_providers.rs @@ -223,7 +223,7 @@ pub async fn delete_openid_provider( let locations = WireguardNetwork::all_using_external_mfa(&mut *transaction).await?; if locations.is_empty() { debug!("No locations are using OIDC provider for external MFA"); - }; + } // fall back to internal MFA in all relevant locations for mut location in locations { debug!( diff --git a/crates/defguard_core/src/enterprise/ldap/client.rs b/crates/defguard_core/src/enterprise/ldap/client.rs index 2d0cdfec01..6e029ac291 100644 --- a/crates/defguard_core/src/enterprise/ldap/client.rs +++ b/crates/defguard_core/src/enterprise/ldap/client.rs @@ -218,7 +218,7 @@ impl super::LDAPConnection { .map(|u| (self.config.user_dn_from_user(u).to_lowercase(), u)) .collect::>(); - for entry in membership_entries.iter_mut() { + for entry in &mut membership_entries { let groupname = entry .attrs .remove(&self.config.ldap_groupname_attr) @@ -335,13 +335,16 @@ impl super::LDAPConnection { } pub(super) async fn list_users(&mut self) -> Result, LdapError> { - let filter = if !self.config.ldap_sync_groups.is_empty() { + let filter = if self.config.ldap_sync_groups.is_empty() { + debug!("No LDAP sync groups defined, searching for all users in the base DN"); + format!("(objectClass={})", self.config.ldap_user_obj_class) + } else { debug!( "LDAP sync groups are defined, filtering users by those groups: {:?}", self.config.ldap_sync_groups ); let mut group_filters = vec![]; - for group in self.config.ldap_sync_groups.iter() { + for group in &self.config.ldap_sync_groups { let group_dn = self.config.group_dn(group); let group_dn_escaped = ldap_escape(&group_dn); group_filters.push(format!( @@ -358,9 +361,6 @@ impl super::LDAPConnection { self.config.ldap_user_obj_class, group_filters.join("") ) - } else { - debug!("No LDAP sync groups defined, searching for all users in the base DN"); - format!("(objectClass={})", self.config.ldap_user_obj_class) }; debug!( diff --git a/crates/defguard_core/src/enterprise/ldap/hash.rs b/crates/defguard_core/src/enterprise/ldap/hash.rs index 7867e621fc..539844aafb 100644 --- a/crates/defguard_core/src/enterprise/ldap/hash.rs +++ b/crates/defguard_core/src/enterprise/ldap/hash.rs @@ -41,10 +41,7 @@ pub fn nthash(password: &str) -> String { #[must_use] pub fn unicode_pwd(password: &str) -> Vec { let quoted = format!("\"{password}\""); - let utf16_bytes: Vec = quoted - .encode_utf16() - .flat_map(|c| c.to_le_bytes()) - .collect(); + let utf16_bytes: Vec = quoted.encode_utf16().flat_map(u16::to_le_bytes).collect(); utf16_bytes } diff --git a/crates/defguard_core/src/enterprise/ldap/mod.rs b/crates/defguard_core/src/enterprise/ldap/mod.rs index c4e5369f54..c756e593f6 100644 --- a/crates/defguard_core/src/enterprise/ldap/mod.rs +++ b/crates/defguard_core/src/enterprise/ldap/mod.rs @@ -236,7 +236,7 @@ impl LDAPConfig { #[must_use] pub(crate) fn get_all_user_obj_classes(&self) -> Vec { let mut obj_classes = vec![self.ldap_user_obj_class.clone()]; - obj_classes.extend(self.ldap_user_auxiliary_obj_classes.to_vec()); + obj_classes.extend(self.ldap_user_auxiliary_obj_classes.clone()); obj_classes } @@ -629,7 +629,7 @@ impl LDAPConnection { user.as_ldap_attrs( &ssha_password, &nt_password, - user_obj_classes.iter().map(|s| s.as_str()).collect(), + user_obj_classes.iter().map(String::as_str).collect(), self.config.ldap_uses_ad, &username_attr, &rdn_attr, @@ -695,7 +695,7 @@ impl LDAPConnection { .attrs .get(&self.config.ldap_groupname_attr) .and_then(|v| v.first()) - .map(|name| name.to_string()) + .map(ToString::to_string) .ok_or_else(|| { LdapError::ObjectNotFound(format!( "Couldn't extract a group name from searchentry {entry:?}." @@ -829,7 +829,7 @@ impl LDAPConnection { .map(|member| self.config.user_dn_from_user(member)) .collect::>(); let member_group_attr = self.config.ldap_group_member_attr.clone(); - let member_refs: HashSet<&str> = member_dns.iter().map(|s| s.as_str()).collect(); + let member_refs: HashSet<&str> = member_dns.iter().map(String::as_str).collect(); for member_ref in member_refs { group_attrs.push((member_group_attr.as_str(), hashset![member_ref])); @@ -841,7 +841,7 @@ impl LDAPConnection { group_name, member_dns .iter() - .map(|dn| dn.as_str()) + .map(String::as_str) .collect::>() .join(", ") ); @@ -902,11 +902,7 @@ impl LDAPConnection { debug!("User {user} is already a member of group {groupname}, skipping"); return Ok(()); } - if !self.group_exists(groupname).await? { - debug!("Group {groupname} doesn't exist in LDAP, creating it"); - self.add_group_with_members(groupname, vec![user]).await?; - debug!("Group {groupname} created and member added in LDAP"); - } else { + if self.group_exists(groupname).await? { debug!("Group {groupname} exists in LDAP, adding user {user} to it"); let group_dn = self.config.group_dn(groupname); self.modify( @@ -919,6 +915,10 @@ impl LDAPConnection { ) .await?; debug!("Added user {user} to group {groupname} in LDAP"); + } else { + debug!("Group {groupname} doesn't exist in LDAP, creating it"); + self.add_group_with_members(groupname, vec![user]).await?; + debug!("Group {groupname} created and member added in LDAP"); } info!("Added user {user} to group {groupname} in LDAP"); Ok(()) diff --git a/crates/defguard_core/src/enterprise/ldap/model.rs b/crates/defguard_core/src/enterprise/ldap/model.rs index 5313109146..643a3c81c8 100644 --- a/crates/defguard_core/src/enterprise/ldap/model.rs +++ b/crates/defguard_core/src/enterprise/ldap/model.rs @@ -99,13 +99,13 @@ impl User { self.email = ldap_user.email.clone(); self.phone = ldap_user.phone.clone(); // It should be ok to update the username if we are not using it in the DN (not as RDN) - if !config.using_username_as_rdn() { - self.username = ldap_user.username.clone(); - } else { + if config.using_username_as_rdn() { debug!( "Not updating username {} from LDAP because it is used as RDN", self.username ); + } else { + self.username = ldap_user.username.clone(); } } diff --git a/crates/defguard_core/src/enterprise/ldap/sync.rs b/crates/defguard_core/src/enterprise/ldap/sync.rs index 201ad6563f..d7a795b6f5 100644 --- a/crates/defguard_core/src/enterprise/ldap/sync.rs +++ b/crates/defguard_core/src/enterprise/ldap/sync.rs @@ -94,11 +94,13 @@ pub enum SyncStatus { } impl SyncStatus { + #[must_use] pub fn is_out_of_sync(&self) -> bool { matches!(self, SyncStatus::OutOfSync) } } +#[must_use] pub fn get_ldap_sync_status() -> SyncStatus { let settings = Settings::get_current_settings(); settings.ldap_sync_status @@ -113,6 +115,7 @@ pub async fn set_ldap_sync_status(status: SyncStatus, pool: &PgPool) -> Result<( Ok(()) } +#[must_use] pub fn is_ldap_desynced() -> bool { get_ldap_sync_status().is_out_of_sync() } @@ -244,7 +247,7 @@ pub(super) fn compute_group_sync_changes<'a>( ldap_config.user_dn_from_user(m) == ldap_config.user_dn_from_user(u) }) }) - .cloned() + .copied() .collect::>(); let missing_from_ldap = members @@ -261,7 +264,9 @@ pub(super) fn compute_group_sync_changes<'a>( "Group {group:?} members missing from Defguard: {missing_from_defguard:?}, missing from LDAP: {missing_from_ldap:?}" ); - if !missing_from_defguard.is_empty() { + if missing_from_defguard.is_empty() { + debug!("Group {group:?} has no members missing from Defguard"); + } else { match authority { Authority::Defguard => { debug!( @@ -276,11 +281,11 @@ pub(super) fn compute_group_sync_changes<'a>( add_defguard.insert(group.clone(), missing_from_defguard); } } - } else { - debug!("Group {group:?} has no members missing from Defguard"); } - if !missing_from_ldap.is_empty() { + if missing_from_ldap.is_empty() { + debug!("Group {group:?} has no members missing from LDAP"); + } else { match authority { Authority::Defguard => { debug!( @@ -295,8 +300,6 @@ pub(super) fn compute_group_sync_changes<'a>( delete_defguard.insert(group.clone(), missing_from_ldap); } } - } else { - debug!("Group {group:?} has no members missing from LDAP"); } } else { match authority { @@ -418,7 +421,7 @@ pub(super) fn extract_intersecting_users( } } - for user in intersecting_users_ldap.into_iter() { + for user in intersecting_users_ldap { if let Some(defguard_user) = defguard_users .iter() .position(|u| ldap_config.user_dn_from_user(u) == ldap_config.user_dn_from_user(&user)) @@ -433,6 +436,7 @@ pub(super) fn extract_intersecting_users( const DEFAULT_LDAP_SYNC_INTERVAL: u64 = 60 * 5; +#[must_use] pub fn get_ldap_sync_interval() -> u64 { let settings = Settings::get_current_settings(); settings @@ -451,7 +455,7 @@ impl super::LDAPConnection { ) -> Result<(), LdapError> { let mut transaction = pool.begin().await?; - for (ldap_user, defguard_user) in intersecting_users.iter_mut() { + for (ldap_user, defguard_user) in &mut intersecting_users { if attrs_different(defguard_user, ldap_user, &self.config) { debug!( "User {defguard_user} attributes differ between LDAP and Defguard, merging..." @@ -860,7 +864,7 @@ impl super::LDAPConnection { self.delete_user(&user).await?; } - for user in changes.add_ldap.iter_mut() { + for user in &mut changes.add_ldap { debug!("Adding user {} to LDAP", user.username); self.add_user(user, None, pool).await?; } diff --git a/crates/defguard_core/src/enterprise/ldap/utils.rs b/crates/defguard_core/src/enterprise/ldap/utils.rs index 97230f2bbc..cdcdd3b55a 100644 --- a/crates/defguard_core/src/enterprise/ldap/utils.rs +++ b/crates/defguard_core/src/enterprise/ldap/utils.rs @@ -126,11 +126,11 @@ pub(crate) async fn ldap_handle_user_modify( debug!("Handling user modify for {old_username} in LDAP"); let mut ldap_connection = LDAPConnection::create().await?; - if !ldap_connection.user_exists(current_user).await? { + if ldap_connection.user_exists(current_user).await? { + debug!("User {current_user} exists in LDAP, modifying it"); + } else { debug!("User {current_user} doesn't exist in LDAP, updating his state first as it may be stale"); ldap_connection.update_users_state(vec![current_user], pool).await?; - } else { - debug!("User {current_user} exists in LDAP, modifying it"); } ldap_connection .modify_user(old_username, current_user) @@ -183,7 +183,7 @@ pub(crate) async fn ldap_remove_user_from_groups( /// Add singular user to multiple groups in ldap. Convenience wrapper around [`ldap_add_users_to_groups`]. pub(crate) async fn ldap_add_user_to_groups(user: &User, groups: HashSet<&str>, pool: &PgPool) { let map = HashMap::from([(user, groups)]); - ldap_add_users_to_groups(map, pool).await + ldap_add_users_to_groups(map, pool).await; } /// Bulk add users to groups in ldap. @@ -194,7 +194,7 @@ pub(crate) async fn ldap_add_users_to_groups( let _: Result<(), LdapError> = with_ldap_status(pool, async { let mut ldap_connection = LDAPConnection::create().await?; let sync_groups = ldap_connection.config.ldap_sync_groups.clone(); - let sync_groups_lookup = sync_groups.iter().map(|s| s.as_str()).collect::>(); + let sync_groups_lookup = sync_groups.iter().map(String::as_str).collect::>(); for (user, groups) in user_groups { let adding_to_sync_groups = groups @@ -223,7 +223,7 @@ pub(crate) async fn ldap_remove_users_from_groups( let _: Result<(), LdapError> = with_ldap_status(pool, async { let mut ldap_connection = LDAPConnection::create().await?; let sync_groups = ldap_connection.config.ldap_sync_groups.clone(); - let sync_groups_lookup = sync_groups.iter().map(|s| s.as_str()).collect::>(); + let sync_groups_lookup = sync_groups.iter().map(String::as_str).collect::>(); for (user, groups) in user_groups { let removing_from_sync_groups = groups @@ -255,15 +255,7 @@ pub(crate) async fn ldap_change_password(user: &mut User, password: &str, po return Ok(()); } let mut ldap_connection = LDAPConnection::create().await?; - if !ldap_connection.user_exists(user).await? { - debug!("User {user} doesn't exist in LDAP, creating it with the provided password"); - let user_groups = user.member_of_names(pool).await?; - ldap_connection.add_user(user, Some(password), pool).await?; - for group in user_groups { - ldap_connection.add_user_to_group(user, &group).await?; - } - debug!("User {user} created in LDAP with the provided password"); - } else { + if ldap_connection.user_exists(user).await? { debug!("User {user} exists in LDAP, changing password"); ldap_connection .set_password(user, password) @@ -276,6 +268,14 @@ pub(crate) async fn ldap_change_password(user: &mut User, password: &str, po debug!( "LDAP password state updated in Defguard for user {user}" ); + } else { + debug!("User {user} doesn't exist in LDAP, creating it with the provided password"); + let user_groups = user.member_of_names(pool).await?; + ldap_connection.add_user(user, Some(password), pool).await?; + for group in user_groups { + ldap_connection.add_user_to_group(user, &group).await?; + } + debug!("User {user} created in LDAP with the provided password"); } Ok(()) diff --git a/crates/defguard_core/src/events.rs b/crates/defguard_core/src/events.rs index c1ac9c892b..744ca87bfc 100644 --- a/crates/defguard_core/src/events.rs +++ b/crates/defguard_core/src/events.rs @@ -30,6 +30,7 @@ pub struct ApiRequestContext { } impl ApiRequestContext { + #[must_use] pub fn new(user_id: Id, username: String, ip: IpAddr, device: String) -> Self { let timestamp = Utc::now().naive_utc(); Self { @@ -57,6 +58,7 @@ pub struct GrpcRequestContext { } impl GrpcRequestContext { + #[must_use] pub fn new( user_id: Id, username: String, @@ -335,6 +337,7 @@ pub struct BidiRequestContext { } impl BidiRequestContext { + #[must_use] pub fn new(user_id: Id, username: String, ip: IpAddr, device_name: String) -> Self { let timestamp = Utc::now().naive_utc(); Self { @@ -422,6 +425,7 @@ pub struct InternalEventContext { } impl InternalEventContext { + #[must_use] pub fn new(user_id: Id, username: String, ip: IpAddr, device: Device) -> Self { let timestamp = Utc::now().naive_utc(); Self { diff --git a/crates/defguard_core/src/grpc/client_mfa.rs b/crates/defguard_core/src/grpc/client_mfa.rs index b2d8fdfe9d..312b7bbe02 100644 --- a/crates/defguard_core/src/grpc/client_mfa.rs +++ b/crates/defguard_core/src/grpc/client_mfa.rs @@ -167,10 +167,10 @@ impl ClientMfaServer { LocationMfaMode::Internal, MfaMethod::Totp | MfaMethod::Email | MfaMethod::Biometric, ) => { - debug!("Location uses internal MFA. Selected method: {selected_method}") + debug!("Location uses internal MFA. Selected method: {selected_method}"); } (LocationMfaMode::External, MfaMethod::Oidc) => { - debug!("Location uses external MFA. Selected method: {selected_method}") + debug!("Location uses external MFA. Selected method: {selected_method}"); } _ => { error!( @@ -247,7 +247,7 @@ impl ClientMfaServer { )); } } - }; + } // generate auth token let token = Self::generate_token(&request.pubkey)?; diff --git a/crates/defguard_core/src/grpc/gateway/client_state.rs b/crates/defguard_core/src/grpc/gateway/client_state.rs index 18b09a4e98..a57ab38eab 100644 --- a/crates/defguard_core/src/grpc/gateway/client_state.rs +++ b/crates/defguard_core/src/grpc/gateway/client_state.rs @@ -119,13 +119,12 @@ impl ClientMap { ); // initialize location map if it doesn't exist yet - let location_map = match self.0.get_mut(&location_id) { - Some(location_map) => location_map, - None => { - // initialize new map for location and immediately return a mutable reference - self.0.insert(location_id, HashMap::new()); - self.0.get_mut(&location_id).unwrap() - } + let location_map = if let Some(location_map) = self.0.get_mut(&location_id) { + location_map + } else { + // initialize new map for location and immediately return a mutable reference + self.0.insert(location_id, HashMap::new()); + self.0.get_mut(&location_id).unwrap() }; // check if client is already connected @@ -134,7 +133,7 @@ impl ClientMap { public_key: public_key.to_string(), location_id, }); - }; + } // add client state to location map let client_state = ClientState::new( @@ -189,10 +188,10 @@ impl ClientMap { .push((client_state.device.clone(), disconnect_event_context)); return false; - }; + } true }); - }; + } Ok(disconnected_clients) } diff --git a/crates/defguard_core/src/grpc/gateway/mod.rs b/crates/defguard_core/src/grpc/gateway/mod.rs index dd5293e575..99240f5a74 100644 --- a/crates/defguard_core/src/grpc/gateway/mod.rs +++ b/crates/defguard_core/src/grpc/gateway/mod.rs @@ -845,7 +845,7 @@ impl gateway_service_server::GatewayService for GatewayServer { })?; } } - }; + } // disconnect inactive clients client_map.disconnect_inactive_vpn_clients_for_location(&location)? diff --git a/crates/defguard_core/src/grpc/mod.rs b/crates/defguard_core/src/grpc/mod.rs index f2a971334f..4dd3b857b0 100644 --- a/crates/defguard_core/src/grpc/mod.rs +++ b/crates/defguard_core/src/grpc/mod.rs @@ -294,6 +294,7 @@ impl GatewayMap { /// /// # Returns /// Returns `HashMap>` from `GatewayMap` + #[must_use] pub fn into_flattened(self) -> HashMap> { self.0 .into_iter() diff --git a/crates/defguard_core/src/handlers/activity_log.rs b/crates/defguard_core/src/handlers/activity_log.rs index 8a5a631ba1..cf85a6b094 100644 --- a/crates/defguard_core/src/handlers/activity_log.rs +++ b/crates/defguard_core/src/handlers/activity_log.rs @@ -159,9 +159,9 @@ pub async fn get_activity_log_events( // add limit and offset to fetch a specific page let limit = DEFAULT_API_PAGE_SIZE; - query_builder.push(" LIMIT ").push_bind(limit as i64); + query_builder.push(" LIMIT ").push_bind(i64::from(limit)); let offset = (pagination.page - 1) * DEFAULT_API_PAGE_SIZE; - query_builder.push(" OFFSET ").push_bind(offset as i64); + query_builder.push(" OFFSET ").push_bind(i64::from(offset)); // fetch filtered events let events = query_builder diff --git a/crates/defguard_core/src/handlers/auth.rs b/crates/defguard_core/src/handlers/auth.rs index 6924f5c760..8790745b74 100644 --- a/crates/defguard_core/src/handlers/auth.rs +++ b/crates/defguard_core/src/handlers/auth.rs @@ -143,47 +143,26 @@ pub(crate) async fn authenticate( // attempt to find user first by username and then by email let mut conn = appstate.pool.acquire().await?; - let mut user = match User::find_by_username_or_email(&mut conn, &username_or_email).await? { - Some(user) => { - // user was found, attempt to authenticate by password first - match user.verify_password(&data.password) { - Ok(()) => user, - Err(err) => { - // password authentication failed, try authenticating with LDAP if configured - if settings.ldap_enabled { - match login_through_ldap(&appstate.pool, &username_or_email, &data.password) - .await - { - Ok(user) => user, - Err(ldap_err) => { - warn!( - "Failed to authenticate user {username_or_email} internally and through LDAP. Internal error: {err}, LDAP error: {ldap_err}" - ); - - log_failed_login_attempt( - &appstate.failed_logins, - &username_or_email, - ); - appstate.emit_event(ApiEvent { - context: ApiRequestContext::new( - user.id, - user.username, - insecure_ip, - user_agent.to_string(), - ), - event: Box::new(ApiEventType::UserLoginFailed { - message: format!( - "Internal and LDAP authentication for {username_or_email} failed. Internal error: {err}, LDAP error: {ldap_err}" - ), - }), - })?; - return Err(WebError::Authorization(ldap_err.to_string())); - } - } - } else { - warn!("Failed to authenticate user {username_or_email}: {err}"); - log_failed_login_attempt(&appstate.failed_logins, &username_or_email); - appstate.emit_event(ApiEvent { + let mut user = if let Some(user) = + User::find_by_username_or_email(&mut conn, &username_or_email).await? + { + // user was found, attempt to authenticate by password first + match user.verify_password(&data.password) { + Ok(()) => user, + Err(err) => { + // password authentication failed, try authenticating with LDAP if configured + if settings.ldap_enabled { + match login_through_ldap(&appstate.pool, &username_or_email, &data.password) + .await + { + Ok(user) => user, + Err(ldap_err) => { + warn!( + "Failed to authenticate user {username_or_email} internally and through LDAP. Internal error: {err}, LDAP error: {ldap_err}" + ); + + log_failed_login_attempt(&appstate.failed_logins, &username_or_email); + appstate.emit_event(ApiEvent { context: ApiRequestContext::new( user.id, user.username, @@ -192,27 +171,44 @@ pub(crate) async fn authenticate( ), event: Box::new(ApiEventType::UserLoginFailed { message: format!( - "Authentication for {username_or_email} failed: {err}" + "Internal and LDAP authentication for {username_or_email} failed. Internal error: {err}, LDAP error: {ldap_err}" ), }), })?; - return Err(WebError::Authorization(err.to_string())); + return Err(WebError::Authorization(ldap_err.to_string())); + } } - } - } - } - None => { - // try to create user from LDAP - debug!("User not found in DB, authenticating user {username_or_email} with LDAP"); - match login_through_ldap(&appstate.pool, &username_or_email, &data.password).await { - Ok(user) => user, - Err(err) => { - info!("Failed to authenticate user {username_or_email} with LDAP: {err}"); + } else { + warn!("Failed to authenticate user {username_or_email}: {err}"); log_failed_login_attempt(&appstate.failed_logins, &username_or_email); + appstate.emit_event(ApiEvent { + context: ApiRequestContext::new( + user.id, + user.username, + insecure_ip, + user_agent.to_string(), + ), + event: Box::new(ApiEventType::UserLoginFailed { + message: format!( + "Authentication for {username_or_email} failed: {err}" + ), + }), + })?; return Err(WebError::Authorization(err.to_string())); } } } + } else { + // try to create user from LDAP + debug!("User not found in DB, authenticating user {username_or_email} with LDAP"); + match login_through_ldap(&appstate.pool, &username_or_email, &data.password).await { + Ok(user) => user, + Err(err) => { + info!("Failed to authenticate user {username_or_email} with LDAP: {err}"); + log_failed_login_attempt(&appstate.failed_logins, &username_or_email); + return Err(WebError::Authorization(err.to_string())); + } + } }; // check if user account is active diff --git a/crates/defguard_core/src/handlers/group.rs b/crates/defguard_core/src/handlers/group.rs index ee0b7b08cf..6cfd2cf365 100644 --- a/crates/defguard_core/src/handlers/group.rs +++ b/crates/defguard_core/src/handlers/group.rs @@ -338,7 +338,7 @@ pub(crate) async fn create_group( } } - for user in members.iter() { + for user in &members { user.add_to_group(&mut *transaction, &group).await?; ldap_user_groups .entry(user) @@ -458,7 +458,7 @@ pub(crate) async fn modify_group( } } - for user in members.iter() { + for user in &members { user.add_to_group(&mut *transaction, &group).await?; add_to_ldap_groups .entry(user) @@ -467,7 +467,7 @@ pub(crate) async fn modify_group( } // Remove outstanding members. - for user in current_members.iter() { + for user in ¤t_members { user.remove_from_group(&mut *transaction, &group).await?; remove_from_ldap_groups .entry(user) diff --git a/crates/defguard_core/src/handlers/network_devices.rs b/crates/defguard_core/src/handlers/network_devices.rs index aafa778d08..1c43874862 100644 --- a/crates/defguard_core/src/handlers/network_devices.rs +++ b/crates/defguard_core/src/handlers/network_devices.rs @@ -266,7 +266,7 @@ pub(crate) async fn check_ip_availability( }) }; return match network.can_assign_ips(&mut transaction, &ips, None).await { - Ok(_) => mkresponse(true, true), + Ok(()) => mkresponse(true, true), Err(NetworkAddressError::NoContainingNetwork(name, ip, networks)) => { warn!( "Provided device IP address {ip} is not in the network {name} range: {networks:?}" @@ -333,16 +333,7 @@ pub(crate) async fn find_available_ips( } transaction.commit().await?; - if split_ips.len() != network.address.len() { - warn!( - "Failed to find available IPs for new device in network {} ({:?})", - network.name, network.address - ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::NOT_FOUND, - }) - } else { + if split_ips.len() == network.address.len() { debug!( "Found addresses {:?} for new device i network {} ({:?})", split_ips, network.name, network.address @@ -351,6 +342,15 @@ pub(crate) async fn find_available_ips( json: json!(split_ips), status: StatusCode::OK, }) + } else { + warn!( + "Failed to find available IPs for new device in network {} ({:?})", + network.name, network.address + ); + Ok(ApiResponse { + json: json!({}), + status: StatusCode::NOT_FOUND, + }) } } diff --git a/crates/defguard_core/src/handlers/user.rs b/crates/defguard_core/src/handlers/user.rs index 2034bdd7ac..86cb2168bd 100644 --- a/crates/defguard_core/src/handlers/user.rs +++ b/crates/defguard_core/src/handlers/user.rs @@ -726,7 +726,7 @@ pub async fn modify_user( group_diff .added .iter() - .map(|g| g.as_str()) + .map(String::as_str) .collect::>(), &appstate.pool, ) @@ -739,7 +739,7 @@ pub async fn modify_user( group_diff .removed .iter() - .map(|g| g.as_str()) + .map(String::as_str) .collect::>(), &appstate.pool, ) diff --git a/crates/defguard_core/src/handlers/wireguard.rs b/crates/defguard_core/src/handlers/wireguard.rs index 44e2776204..54e4d27bd8 100644 --- a/crates/defguard_core/src/handlers/wireguard.rs +++ b/crates/defguard_core/src/handlers/wireguard.rs @@ -1091,7 +1091,7 @@ pub(crate) async fn delete_device( appstate.emit_event(ApiEvent { context, event: Box::new(ApiEventType::UserDeviceRemoved { device, owner }), - })? + })?; } DeviceType::Network => { if let Some(network_info) = device_info.network_info.first() { diff --git a/crates/defguard_core/src/wireguard_peer_disconnect.rs b/crates/defguard_core/src/wireguard_peer_disconnect.rs index e0e0dccd54..06be7734d9 100644 --- a/crates/defguard_core/src/wireguard_peer_disconnect.rs +++ b/crates/defguard_core/src/wireguard_peer_disconnect.rs @@ -172,7 +172,7 @@ pub async fn run_periodic_peer_disconnect( .and_then(|(ip, _)| IpAddr::from_str(ip).ok()) // endpoint is a `text` column in the db so we have to // handle potential parsing issues here - .unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))); + .unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED)); let event = InternalEvent::DesktopClientMfaDisconnected { context: InternalEventContext::new(user.id, user.username, ip, device), location: location.clone(), diff --git a/crates/defguard_event_logger/src/description.rs b/crates/defguard_event_logger/src/description.rs index dfd6de7d0e..1ca6377198 100644 --- a/crates/defguard_event_logger/src/description.rs +++ b/crates/defguard_event_logger/src/description.rs @@ -10,6 +10,7 @@ use crate::message::{DefguardEvent, EnrollmentEvent, VpnEvent}; +#[must_use] pub fn get_defguard_event_description(event: &DefguardEvent) -> Option { match event { DefguardEvent::UserLogin => None, @@ -70,7 +71,7 @@ pub fn get_defguard_event_description(event: &DefguardEvent) -> Option { "disabled" }; description = format!("{description}, status changed to {status_change_text}"); - }; + } Some(description) } DefguardEvent::UserGroupsModified { @@ -259,6 +260,7 @@ pub fn get_defguard_event_description(event: &DefguardEvent) -> Option { } } +#[must_use] pub fn get_vpn_event_description(event: &VpnEvent) -> Option { match event { VpnEvent::ConnectedToMfaLocation { @@ -288,6 +290,7 @@ pub fn get_vpn_event_description(event: &VpnEvent) -> Option { } } +#[must_use] pub fn get_enrollment_event_description(event: &EnrollmentEvent) -> Option { match event { EnrollmentEvent::EnrollmentStarted => Some("User started enrollment process".to_string()), diff --git a/crates/defguard_event_logger/src/message.rs b/crates/defguard_event_logger/src/message.rs index 9100416fbf..26b4145689 100644 --- a/crates/defguard_event_logger/src/message.rs +++ b/crates/defguard_event_logger/src/message.rs @@ -23,6 +23,7 @@ pub struct EventLoggerMessage { } impl EventLoggerMessage { + #[must_use] pub fn new(context: EventContext, event: LoggerEvent) -> Self { Self { context, event } } @@ -46,6 +47,7 @@ pub struct EventContext { } impl EventContext { + #[must_use] pub fn from_api_context( val: ApiRequestContext, location: Option>, @@ -62,6 +64,7 @@ impl EventContext { } } + #[must_use] pub fn from_bidi_context( val: BidiRequestContext, location: Option>, @@ -78,6 +81,7 @@ impl EventContext { } } + #[must_use] pub fn from_internal_context( val: InternalEventContext, location: Option>, diff --git a/crates/defguard_event_router/src/lib.rs b/crates/defguard_event_router/src/lib.rs index c6807d9106..0b53148bd5 100644 --- a/crates/defguard_event_router/src/lib.rs +++ b/crates/defguard_event_router/src/lib.rs @@ -57,6 +57,7 @@ pub struct RouterReceiverSet { } impl RouterReceiverSet { + #[must_use] pub fn new( api: UnboundedReceiver, grpc: UnboundedReceiver, @@ -121,33 +122,21 @@ impl EventRouter { loop { // Receive an event from one of the component event channels let event = tokio::select! { - event = self.receivers.api.recv() => match event { - Some(api_event) => Event::Api(api_event), - None => { - error!("API event channel closed"); - return Err(EventRouterError::ApiEventChannelClosed); - } + event = self.receivers.api.recv() => if let Some(api_event) = event { Event::Api(api_event) } else { + error!("API event channel closed"); + return Err(EventRouterError::ApiEventChannelClosed); }, - event = self.receivers.grpc.recv() => match event { - Some(grpc_event) => Event::Grpc(Box::new(grpc_event)), - None => { - error!("gRPC event channel closed"); - return Err(EventRouterError::GrpcEventChannelClosed); - } + event = self.receivers.grpc.recv() => if let Some(grpc_event) = event { Event::Grpc(Box::new(grpc_event)) } else { + error!("gRPC event channel closed"); + return Err(EventRouterError::GrpcEventChannelClosed); }, - event = self.receivers.bidi.recv() => match event { - Some(bidi_event) => Event::Bidi(bidi_event), - None => { - error!("Bidi gRPC stream event channel closed"); - return Err(EventRouterError::BidiEventChannelClosed); - } + event = self.receivers.bidi.recv() => if let Some(bidi_event) = event { Event::Bidi(bidi_event) } else { + error!("Bidi gRPC stream event channel closed"); + return Err(EventRouterError::BidiEventChannelClosed); }, - event = self.receivers.internal.recv() => match event { - Some(internal_event) => Event::Internal(Box::new(internal_event)), - None => { - error!("Internal event channel closed"); - return Err(EventRouterError::InternalEventChannelClosed); - } + event = self.receivers.internal.recv() => if let Some(internal_event) = event { Event::Internal(Box::new(internal_event)) } else { + error!("Internal event channel closed"); + return Err(EventRouterError::InternalEventChannelClosed); }, }; From 98e21ebe7be3b17249353e397250affd7f175359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Thu, 14 Aug 2025 14:44:04 +0200 Subject: [PATCH 3/3] Remove wrong example --- crates/defguard_event_router/src/lib.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/crates/defguard_event_router/src/lib.rs b/crates/defguard_event_router/src/lib.rs index 0b53148bd5..335ca17838 100644 --- a/crates/defguard_event_router/src/lib.rs +++ b/crates/defguard_event_router/src/lib.rs @@ -9,24 +9,13 @@ //! //! The event router acts as a central hub for all application events: //! -//! 1. Components (web API, gRPC server etc.) send events to the router via the `event_tx` MPSC channel +//! 1. Components (web API, gRPC server etc.) send events to the router via the `event_tx` +//! MPSC channel. //! 2. The router processes these events and forwards them to the appropriate services: //! - Activity log events go to the event logger service //! - WireGuard events go to the gateway service //! - Mail events go to the mail service //! - etc. -//! -//! # Usage -//! -//! To use the event router, components should send `MainEvent` instances to the -//! event channel. The router will handle routing these events to the appropriate -//! services based on their type. -//! -//! ``` -//! // Example: -//! let event = MainEvent::UserLogin { context: user_context }; -//! event_tx.send(event).await.unwrap(); -//! ``` use std::sync::Arc;