From 3a905edb8d6298bb2d9b16181ed9652c6f186a36 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Wed, 15 Apr 2026 15:02:22 +0200 Subject: [PATCH 01/15] Initial version --- Cargo.lock | 867 ++++++++++++++---- README.md | 19 + example.users.toml | 5 + pgdog-config/src/core.rs | 14 +- pgdog-config/src/users.rs | 20 + pgdog/Cargo.toml | 2 + .../backend/auth/azure_workload_identity.rs | 99 ++ pgdog/src/backend/auth/mod.rs | 1 + pgdog/src/backend/error.rs | 3 + pgdog/src/backend/pool/address.rs | 5 + pgdog/src/backend/server.rs | 5 + 11 files changed, 839 insertions(+), 201 deletions(-) create mode 100644 pgdog/src/backend/auth/azure_workload_identity.rs diff --git a/Cargo.lock b/Cargo.lock index 98f6c842c..095636743 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.0" @@ -126,6 +117,29 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-compression" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1" +dependencies = [ + "compression-codecs", + "compression-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + [[package]] name = "async-trait" version = "0.1.88" @@ -134,7 +148,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -417,7 +431,7 @@ dependencies = [ "http 1.3.1", "http-body 0.4.6", "hyper 0.14.32", - "hyper 1.6.0", + "hyper 1.9.0", "hyper-rustls 0.24.2", "hyper-rustls 0.27.7", "hyper-util", @@ -550,18 +564,54 @@ dependencies = [ ] [[package]] -name = "backtrace" -version = "0.3.75" +name = "azure_core" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "688882dc4a96b0ea158299d590fad91c471eced6403fd9a9ea1992c14397f25f" dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", + "async-lock", + "async-trait", + "azure_core_macros", + "bytes", + "futures", + "pin-project", + "rustc_version", + "serde", + "serde_json", + "tokio", + "tracing", + "typespec", + "typespec_client_core", +] + +[[package]] +name = "azure_core_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70066e34b8db2c3f0b852c56a99333bd25fdedfb8850cd95dddf930928b47b80" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "tracing", +] + +[[package]] +name = "azure_identity" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8392bbf0028c43df2f69422825721614f47e12fd601f9056df2c18d35c57e0" +dependencies = [ + "async-lock", + "async-trait", + "azure_core", + "futures", + "pin-project", + "serde", + "serde_json", + "time", + "tracing", + "url", ] [[package]] @@ -630,7 +680,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.101", + "syn 2.0.117", "which 4.4.2", ] @@ -651,7 +701,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -663,7 +713,7 @@ dependencies = [ "bitflags 2.9.1", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -671,7 +721,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -745,7 +795,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -790,9 +840,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bytes-utils" @@ -846,6 +896,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.41" @@ -857,7 +918,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -902,7 +963,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -949,6 +1010,23 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "compression-codecs" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7" +dependencies = [ + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1008,6 +1086,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.3.0" @@ -1023,6 +1110,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "critical-section" version = "1.2.0" @@ -1139,7 +1235,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1150,7 +1246,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1201,11 +1297,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", + "serde_core", ] [[package]] @@ -1226,7 +1323,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1236,7 +1333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1257,7 +1354,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1280,7 +1377,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1337,7 +1434,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1393,6 +1490,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -1450,6 +1557,16 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flume" version = "0.11.1" @@ -1576,7 +1693,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -1658,15 +1775,23 @@ checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.2.0", "wasi 0.14.2+wasi-0.2.4", ] [[package]] -name = "gimli" -version = "0.31.1" +name = "getrandom" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", +] [[package]] name = "glob" @@ -1917,7 +2042,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.9", "tokio", "tower-service", "tracing", @@ -1926,13 +2051,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2 0.4.10", "http 1.3.1", "http-body 1.0.1", @@ -1968,7 +2094,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.3.1", - "hyper 1.6.0", + "hyper 1.9.0", "hyper-util", "rustls 0.23.27", "rustls-native-certs 0.8.1", @@ -1986,7 +2112,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper 1.9.0", "hyper-util", "native-tls", "tokio", @@ -1996,22 +2122,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.11" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", "futures-util", "http 1.3.1", "http-body 1.0.1", - "hyper 1.6.0", + "hyper 1.9.0", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.5.9", + "system-configuration 0.7.0", "tokio", + "tower-layer", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -2124,6 +2256,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -2178,7 +2316,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -2187,7 +2325,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2", + "socket2 0.5.9", "widestring", "windows-sys 0.48.0", "winreg", @@ -2199,6 +2337,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -2250,10 +2398,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -2289,11 +2439,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.172" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libloading" @@ -2476,18 +2632,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2594,9 +2751,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-derive" @@ -2606,7 +2763,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -2648,15 +2805,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -2690,7 +2838,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -2813,7 +2961,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -2862,6 +3010,8 @@ dependencies = [ "async-trait", "aws-config", "aws-sdk-rds", + "azure_core", + "azure_identity", "base64 0.22.1", "bytes", "cc", @@ -2874,7 +3024,7 @@ dependencies = [ "futures", "hickory-resolver", "http-body-util", - "hyper 1.6.0", + "hyper 1.9.0", "hyper-util", "indexmap", "lazy_static", @@ -2901,7 +3051,7 @@ dependencies = [ "serde", "serde_json", "sha1", - "socket2", + "socket2 0.5.9", "stats_alloc", "tempfile", "thiserror 2.0.12", @@ -2961,7 +3111,7 @@ version = "0.1.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -3063,7 +3213,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -3092,7 +3242,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -3201,7 +3351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -3215,9 +3365,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3248,7 +3398,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.101", + "syn 2.0.117", "tempfile", ] @@ -3262,7 +3412,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -3296,9 +3446,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3309,6 +3459,12 @@ version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -3336,6 +3492,17 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -3374,6 +3541,12 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "ratatui" version = "0.30.0-alpha.3" @@ -3484,7 +3657,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -3561,7 +3734,7 @@ dependencies = [ "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.9.0", "hyper-rustls 0.27.7", "hyper-tls", "hyper-util", @@ -3578,7 +3751,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", "tower", @@ -3590,6 +3763,42 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.9.0", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "resolv-conf" version = "0.7.4" @@ -3707,7 +3916,7 @@ dependencies = [ "ordered-float", "parking_lot", "rand 0.9.2", - "reqwest", + "reqwest 0.12.15", "serde_json", "serial_test", "sqlx", @@ -3734,12 +3943,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -3940,7 +4143,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4031,22 +4234,32 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4057,19 +4270,20 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -4115,7 +4329,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4125,7 +4339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -4136,7 +4350,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -4167,9 +4381,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -4195,6 +4409,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + [[package]] name = "simdutf8" version = "0.1.5" @@ -4235,6 +4455,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "spin" version = "0.5.2" @@ -4320,7 +4550,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4343,7 +4573,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.101", + "syn 2.0.117", "tempfile", "tokio", "url", @@ -4512,7 +4742,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4534,9 +4764,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4560,7 +4790,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4574,6 +4804,17 @@ dependencies = [ "system-configuration-sys", ] +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.9.1", + "core-foundation 0.9.4", + "system-configuration-sys", +] + [[package]] name = "system-configuration-sys" version = "0.6.0" @@ -4698,7 +4939,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4709,7 +4950,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4744,31 +4985,32 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "itoa", "libc", "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -4801,31 +5043,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" dependencies = [ - "backtrace", "bytes", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.3", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -4858,7 +5099,7 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand 0.9.2", - "socket2", + "socket2 0.5.9", "tokio", "tokio-util", "whoami", @@ -4966,6 +5207,29 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "async-compression", + "bitflags 2.9.1", + "bytes", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "iri-string", + "pin-project-lite", + "tokio", + "tokio-util", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -4980,9 +5244,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -4992,20 +5256,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -5065,6 +5329,57 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "typespec" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "247afbeabe0c383f630d0fdcb4fb92818c31cd3fe5d293335daff8cac79d4e0f" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "typespec_client_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66166c78ee5b5a03b665a639899414a468f645f58dba3c8154b82d64847d227b" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "dyn-clone", + "futures", + "pin-project", + "rand 0.10.1", + "reqwest 0.13.2", + "serde", + "serde_json", + "time", + "tokio", + "tracing", + "typespec", + "typespec_macros", + "url", + "uuid", +] + +[[package]] +name = "typespec_macros" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d17153fde258b3c862cecffad95e185c0eb83e619e76542c4b3ed9828af840f0" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", +] + [[package]] name = "ucd-trie" version = "0.1.7" @@ -5121,6 +5436,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.7.1" @@ -5164,13 +5485,15 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.16.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ "atomic", - "getrandom 0.3.3", - "serde", + "getrandom 0.4.2", + "js-sys", + "serde_core", + "wasm-bindgen", ] [[package]] @@ -5230,6 +5553,24 @@ dependencies = [ "wit-bindgen-rt", ] +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasite" version = "0.1.0" @@ -5238,48 +5579,32 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.101", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5287,31 +5612,78 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.101", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.9.1", + "hashbrown 0.15.3", + "indexmap", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -5461,7 +5833,7 @@ dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -5482,7 +5854,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings 0.4.2", ] @@ -5494,7 +5866,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.3", "windows-threading", ] @@ -5506,7 +5878,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -5517,7 +5889,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -5526,6 +5898,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-numerics" version = "0.2.0" @@ -5533,7 +5911,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5553,7 +5931,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5562,7 +5940,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5571,7 +5949,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5601,6 +5979,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -5654,7 +6041,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5820,6 +6207,26 @@ version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + [[package]] name = "wit-bindgen-rt" version = "0.39.0" @@ -5829,6 +6236,74 @@ dependencies = [ "bitflags 2.9.1", ] +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.9.1", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "workspace_root" version = "0.2.0" @@ -5879,7 +6354,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", "synstructure", ] @@ -5900,7 +6375,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] [[package]] @@ -5920,7 +6395,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", "synstructure", ] @@ -5960,5 +6435,11 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.117", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/README.md b/README.md index 874983a58..5d52a0a29 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,25 @@ When any user has `server_auth = "rds_iam"`, the following settings must be conf - `tls_verify` must **not** be `"disabled"`. - `passthrough_auth` must be `"disabled"`. +#### Azure Workload Identity authentication + +PgDog can also use Azure Workload Identity for PgDog-to-PostgreSQL authentication, while keeping client-to-PgDog authentication unchanged. This is configured on a per-user basis, similarly to RDS IAM: + +**Example** + +```toml +[[users]] +name = "alice" +database = "pgdog" +password = "client-password" +server_auth = "azure_workload_identity" +``` + +When any user has `server_auth = "azure_workload_identity"`, the following settings must be configured as well: + +- `tls_verify` must **not** be `"disabled"`. +- `passthrough_auth` must be `"disabled"`. + ### Sharding 📘 **[Sharding](https://docs.pgdog.dev/features/sharding/)** diff --git a/example.users.toml b/example.users.toml index d3fcd757f..8bb78cfa5 100644 --- a/example.users.toml +++ b/example.users.toml @@ -17,3 +17,8 @@ password = "pgdog" # this only affects how PgDog authenticates to PostgreSQL servers. # server_auth = "rds_iam" # server_iam_region = "us-east-1" # optional; auto-inferred from RDS hostname when omitted + +# Example: backend authentication with Azure Workload Identity token generation. +# PgDog still authenticates the client as configured by `general.auth_type`; +# this only affects how PgDog authenticates to PostgreSQL servers. +# server_auth = "azure_workload_identiy" diff --git a/pgdog-config/src/core.rs b/pgdog-config/src/core.rs index 856518a89..1614872bb 100644 --- a/pgdog-config/src/core.rs +++ b/pgdog-config/src/core.rs @@ -112,25 +112,23 @@ impl ConfigAndUsers { } fn validate_server_auth(&self) -> Result<(), Error> { - let has_rds_iam_user = self - .users - .users - .iter() - .any(|user| user.server_auth == ServerAuth::RdsIam); + let is_external_identity = self.users.users.iter().any(|user| { + [ServerAuth::RdsIam, ServerAuth::AzureWorkloadIdentity].contains(&user.server_auth) + }); - if !has_rds_iam_user { + if !is_external_identity { return Ok(()); } if self.config.general.passthrough_auth != PassthroughAuth::Disabled { return Err(Error::ParseError( - "\"passthrough_auth\" must be \"disabled\" when any user has \"server_auth = \\\"rds_iam\\\"\"".into(), + "\"passthrough_auth\" must be \"disabled\" when any user has \"server_auth = \\\"rds_iam\\\"\" or \"server_auth = \\\"azure_workload_identity\\\"\"".into(), )); } if self.config.general.tls_verify == TlsVerifyMode::Disabled { return Err(Error::ParseError( - "\"tls_verify\" cannot be \"disabled\" when any user has \"server_auth = \\\"rds_iam\\\"\"".into(), + "\"tls_verify\" cannot be \"disabled\" when any user has \"server_auth = \\\"rds_iam\\\"\" or \"server_auth = \\\"azure_workload_identity\\\"\"".into(), )); } diff --git a/pgdog-config/src/users.rs b/pgdog-config/src/users.rs index d99f6d584..fe6e300a5 100644 --- a/pgdog-config/src/users.rs +++ b/pgdog-config/src/users.rs @@ -135,12 +135,17 @@ pub enum ServerAuth { Password, /// Generate an AWS RDS IAM auth token per connection attempt. RdsIam, + AzureWorkloadIdentity, } impl ServerAuth { pub fn rds_iam(&self) -> bool { matches!(self, Self::RdsIam) } + + pub fn azure_workload_identity(&self) -> bool { + matches!(self, Self::AzureWorkloadIdentity) + } } /// User allowed to connect to pgDog. @@ -539,4 +544,19 @@ server_iam_region = "us-east-1" assert_eq!(user.server_auth, ServerAuth::RdsIam); assert_eq!(user.server_iam_region.as_deref(), Some("us-east-1")); } + + #[test] + fn test_user_server_auth_azure_workload_identity() { + let source = r#" +[[users]] +name = "alice" +database = "db" +password = "secret" +server_auth = "azure_workload_identity" +"#; + + let users: Users = toml::from_str(source).unwrap(); + let user = users.users.first().unwrap(); + assert_eq!(user.server_auth, ServerAuth::AzureWorkloadIdentity); + } } diff --git a/pgdog/Cargo.toml b/pgdog/Cargo.toml index 7c62c28c4..8b05ff038 100644 --- a/pgdog/Cargo.toml +++ b/pgdog/Cargo.toml @@ -69,6 +69,8 @@ pgdog-config = { path = "../pgdog-config" } pgdog-vector = { path = "../pgdog-vector" } pgdog-stats = { path = "../pgdog-stats" } pgdog-postgres-types = { path = "../pgdog-postgres-types"} +azure_identity = "0.34.0" +azure_core = "0.34.0" [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = "0.6" diff --git a/pgdog/src/backend/auth/azure_workload_identity.rs b/pgdog/src/backend/auth/azure_workload_identity.rs new file mode 100644 index 000000000..330e7d5e3 --- /dev/null +++ b/pgdog/src/backend/auth/azure_workload_identity.rs @@ -0,0 +1,99 @@ +use crate::backend::{pool::Address, Error}; +use azure_core::credentials::TokenCredential; +use azure_identity::WorkloadIdentityCredential; + +pub async fn token(addr: &Address) -> Result { + #[cfg(test)] + if let Some(token) = test_token_override() { + return Ok(token); + } + + let credential = WorkloadIdentityCredential::new(None).map_err(|error| { + Error::AzureIamToken(format!( + "failed to build workload identity credential for {}@{}:{}: {}", + addr.user, addr.host, addr.port, error + )) + })?; + + credential + .get_token( + &["https://ossrdbms-aad.database.windows.net/.default"], + None, + ) + .await + .map(|token| token.token.secret().to_string()) + .map_err(|error| { + Error::AzureIamToken(format!( + "failed to get Azure AD token for {}@{}:{}: {}", + addr.user, addr.host, addr.port, error + )) + }) +} + +#[cfg(test)] +fn test_token_override() -> Option { + TEST_TOKEN_OVERRIDE.lock().clone() +} + +#[cfg(test)] +static TEST_TOKEN_OVERRIDE: once_cell::sync::Lazy>> = + once_cell::sync::Lazy::new(|| parking_lot::Mutex::new(None)); + +#[cfg(test)] +mod tests { + use std::env; + + use crate::backend::pool::Address; + use crate::config::ServerAuth; + + use super::*; + + struct EnvVarGuard { + key: &'static str, + previous: Option, + } + + impl EnvVarGuard { + fn set(key: &'static str, value: &str) -> Self { + let previous = env::var(key).ok(); + env::set_var(key, value); + Self { key, previous } + } + } + + impl Drop for EnvVarGuard { + fn drop(&mut self) { + if let Some(previous) = self.previous.take() { + env::set_var(self.key, previous); + } else { + env::remove_var(self.key); + } + } + } + + #[tokio::test] + async fn test_token_contains_expected_query_fields() { + let _azure_client_id = EnvVarGuard::set("AZURE_CLIENT_ID", "EXAMPLE"); + let _azure_tenant_id = EnvVarGuard::set("AZURE_TENANT_ID", "EXAMPLE"); + let _azure_token_file_path = EnvVarGuard::set("AZURE_FEDERATED_TOKEN_FILE", "/tmp/example"); + + let addr = Address { + host: "my-awesome-db.postgres.database.azure.com".into(), + port: 5432, + database_name: "postgres".into(), + user: "db_user".into(), + passwords: vec![String::new()], + database_number: 0, + server_auth: ServerAuth::AzureWorkloadIdentity, + server_iam_region: None, + }; + + let token = token(&addr).await.unwrap(); + assert!(token.starts_with( + "my-awesome-db.postgres.database.azure.com:5432/?Action=connect&DBUser=db_user" + )); + assert!(token.contains("https://sts.windows.net/")); + assert!(token.contains("https://management.azure.com")); + assert!(token.contains("appid")); + } +} diff --git a/pgdog/src/backend/auth/mod.rs b/pgdog/src/backend/auth/mod.rs index 9fb005282..cda4083ee 100644 --- a/pgdog/src/backend/auth/mod.rs +++ b/pgdog/src/backend/auth/mod.rs @@ -1 +1,2 @@ +pub mod azure_workload_identity; pub mod rds_iam; diff --git a/pgdog/src/backend/error.rs b/pgdog/src/backend/error.rs index f1dc18c74..673588b24 100644 --- a/pgdog/src/backend/error.rs +++ b/pgdog/src/backend/error.rs @@ -120,6 +120,9 @@ pub enum Error { #[error("RDS IAM token generation failed: {0}")] RdsIamToken(String), + #[error("Azure Workload identity token generation failed: {0}")] + AzureIamToken(String), + #[error("pub/sub channel disabled")] PubSubDisabled, diff --git a/pgdog/src/backend/pool/address.rs b/pgdog/src/backend/pool/address.rs index 25ae5cf86..c8a7a2218 100644 --- a/pgdog/src/backend/pool/address.rs +++ b/pgdog/src/backend/pool/address.rs @@ -66,6 +66,8 @@ impl Address { }, passwords: if server_auth.rds_iam() { vec![] + } else if server_auth.azure_workload_identity() { + vec![] } else if let Some(password) = database.password.clone() { vec![password] } else if let Some(password) = user.server_password.clone() { @@ -83,6 +85,9 @@ impl Address { match self.server_auth { ServerAuth::Password => Ok(self.passwords.clone()), ServerAuth::RdsIam => Ok(vec![crate::backend::auth::rds_iam::token(self).await?]), + ServerAuth::AzureWorkloadIdentity => Ok(vec![ + crate::backend::auth::azure_workload_identity::token(self).await?, + ]), } } diff --git a/pgdog/src/backend/server.rs b/pgdog/src/backend/server.rs index 9fb8c53f2..06a9ab841 100644 --- a/pgdog/src/backend/server.rs +++ b/pgdog/src/backend/server.rs @@ -1240,6 +1240,11 @@ pub mod test { server_task.await.unwrap(); } + #[tokio::test] + async fn test_connect_azure_sql_workload_identity_uses_dynamic_token_not_static_password() { + // TODO_AZURE_WORKLOAD_IDENTITY + } + #[tokio::test] async fn test_simple_query() { let mut server = test_server().await; From ee9ff5a241d76af9182ef9185f3841bb5415fc1d Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 12:21:18 +0200 Subject: [PATCH 02/15] feat: adding some test --- .../backend/auth/azure_workload_identity.rs | 7 ++- pgdog/src/backend/server.rs | 55 ++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/pgdog/src/backend/auth/azure_workload_identity.rs b/pgdog/src/backend/auth/azure_workload_identity.rs index 330e7d5e3..bfbed392c 100644 --- a/pgdog/src/backend/auth/azure_workload_identity.rs +++ b/pgdog/src/backend/auth/azure_workload_identity.rs @@ -35,6 +35,11 @@ fn test_token_override() -> Option { TEST_TOKEN_OVERRIDE.lock().clone() } +#[cfg(test)] +pub(crate) fn set_test_token_override(token: Option) { + *TEST_TOKEN_OVERRIDE.lock() = token; +} + #[cfg(test)] static TEST_TOKEN_OVERRIDE: once_cell::sync::Lazy>> = once_cell::sync::Lazy::new(|| parking_lot::Mutex::new(None)); @@ -92,7 +97,7 @@ mod tests { assert!(token.starts_with( "my-awesome-db.postgres.database.azure.com:5432/?Action=connect&DBUser=db_user" )); - assert!(token.contains("https://sts.windows.net/")); + assert!(token.contains("https://sts.windows.net")); assert!(token.contains("https://management.azure.com")); assert!(token.contains("appid")); } diff --git a/pgdog/src/backend/server.rs b/pgdog/src/backend/server.rs index 06a9ab841..b1926359a 100644 --- a/pgdog/src/backend/server.rs +++ b/pgdog/src/backend/server.rs @@ -1242,7 +1242,60 @@ pub mod test { #[tokio::test] async fn test_connect_azure_sql_workload_identity_uses_dynamic_token_not_static_password() { - // TODO_AZURE_WORKLOAD_IDENTITY + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + let expected_secret = "token-for-test".to_string(); + let server_task = tokio::spawn({ + let expected_secret = expected_secret.clone(); + async move { + let (mut socket, _) = listener.accept().await.unwrap(); + + let startup = Startup::from_stream(&mut socket).await.unwrap(); + let startup = if matches!(startup, Startup::Ssl) { + socket.write_all(b"N").await.unwrap(); + Startup::from_stream(&mut socket).await.unwrap() + } else { + startup + }; + assert!(matches!(startup, Startup::Startup { .. })); + + socket + .write_all(&Authentication::ClearTextPassword.to_bytes().unwrap()) + .await + .unwrap(); + + let password = read_password_message(&mut socket).await; + assert_eq!(password.password(), Some(expected_secret.as_str())); + + socket + .write_all(&Authentication::Ok.to_bytes().unwrap()) + .await + .unwrap(); + socket + .write_all(&BackendKeyData::new().to_bytes().unwrap()) + .await + .unwrap(); + socket + .write_all(&ReadyForQuery::idle().to_bytes().unwrap()) + .await + .unwrap(); + } + }); + + let mut addr = Address::new_test(); + addr.port = port; + addr.server_auth = crate::config::ServerAuth::AzureWorkloadIdentity; + addr.passwords = vec!["wrong-password".into()]; + + crate::backend::auth::azure_workload_identity::set_test_token_override(Some( + expected_secret, + )); + let result = Server::connect(&addr, ServerOptions::default(), ConnectReason::Other).await; + crate::backend::auth::azure_workload_identity::set_test_token_override(None); + + let server = result.unwrap(); + drop(server); + server_task.await.unwrap(); } #[tokio::test] From 629e19c84681b5f642801b367ed33f0fbd06e008 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 14:02:21 +0200 Subject: [PATCH 03/15] error naming --- pgdog/src/backend/auth/azure_workload_identity.rs | 11 +++-------- pgdog/src/backend/error.rs | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/pgdog/src/backend/auth/azure_workload_identity.rs b/pgdog/src/backend/auth/azure_workload_identity.rs index bfbed392c..5169dcf0e 100644 --- a/pgdog/src/backend/auth/azure_workload_identity.rs +++ b/pgdog/src/backend/auth/azure_workload_identity.rs @@ -9,7 +9,7 @@ pub async fn token(addr: &Address) -> Result { } let credential = WorkloadIdentityCredential::new(None).map_err(|error| { - Error::AzureIamToken(format!( + Error::AzureWorkloadIdentityToken(format!( "failed to build workload identity credential for {}@{}:{}: {}", addr.user, addr.host, addr.port, error )) @@ -23,7 +23,7 @@ pub async fn token(addr: &Address) -> Result { .await .map(|token| token.token.secret().to_string()) .map_err(|error| { - Error::AzureIamToken(format!( + Error::AzureWorkloadIdentityToken(format!( "failed to get Azure AD token for {}@{}:{}: {}", addr.user, addr.host, addr.port, error )) @@ -35,11 +35,6 @@ fn test_token_override() -> Option { TEST_TOKEN_OVERRIDE.lock().clone() } -#[cfg(test)] -pub(crate) fn set_test_token_override(token: Option) { - *TEST_TOKEN_OVERRIDE.lock() = token; -} - #[cfg(test)] static TEST_TOKEN_OVERRIDE: once_cell::sync::Lazy>> = once_cell::sync::Lazy::new(|| parking_lot::Mutex::new(None)); @@ -97,7 +92,7 @@ mod tests { assert!(token.starts_with( "my-awesome-db.postgres.database.azure.com:5432/?Action=connect&DBUser=db_user" )); - assert!(token.contains("https://sts.windows.net")); + assert!(token.contains("https://sts.windows.net/")); assert!(token.contains("https://management.azure.com")); assert!(token.contains("appid")); } diff --git a/pgdog/src/backend/error.rs b/pgdog/src/backend/error.rs index 673588b24..6024079df 100644 --- a/pgdog/src/backend/error.rs +++ b/pgdog/src/backend/error.rs @@ -120,8 +120,8 @@ pub enum Error { #[error("RDS IAM token generation failed: {0}")] RdsIamToken(String), - #[error("Azure Workload identity token generation failed: {0}")] - AzureIamToken(String), + #[error("Azure Workload Identity token generation failed: {0}")] + AzureWorkloadIdentityToken(String), #[error("pub/sub channel disabled")] PubSubDisabled, From 54d17e2d7f997d4f0aadc4c836ac9e7d97a34774 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 14:12:21 +0200 Subject: [PATCH 04/15] README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d52a0a29..7f780e1f9 100644 --- a/README.md +++ b/README.md @@ -198,10 +198,11 @@ role = "auto" 📘 **[Authentication](https://docs.pgdog.dev/features/authentication/)** -PgDog supports two authentication methods: +PgDog supports three authentication methods: 1. Password-based 2. AWS RDS IAM +3. Azure Workload Identity #### Password-based authentication From 6c7d35e707a0f5da32adf08dc4b420f4992fcc95 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 19:34:39 +0200 Subject: [PATCH 05/15] fix: rng --- pgdog-config/src/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgdog-config/src/util.rs b/pgdog-config/src/util.rs index 64c103418..6e39d55d1 100644 --- a/pgdog-config/src/util.rs +++ b/pgdog-config/src/util.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use rand::{distr::Alphanumeric, Rng}; +use rand::{distr::Alphanumeric, RngExt}; pub fn human_duration_optional(duration: Option) -> String { if let Some(duration) = duration { From 608599679a42564ece96be48b58be044d5794ced Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 19:42:48 +0200 Subject: [PATCH 06/15] fix: user schema json --- .schema/users.schema.json | 81 ++++++++++----------------------------- 1 file changed, 21 insertions(+), 60 deletions(-) diff --git a/.schema/users.schema.json b/.schema/users.schema.json index d6f29a9fc..668860b41 100644 --- a/.schema/users.schema.json +++ b/.schema/users.schema.json @@ -80,6 +80,11 @@ "description": "Generate an AWS RDS IAM auth token per connection attempt.", "type": "string", "const": "rds_iam" + }, + { + "description": "Generate an Azure Workload Identity auth token per connection attempt.", + "type": "string", + "const": "azure_workload_identity" } ] }, @@ -94,10 +99,7 @@ }, "cross_shard_disabled": { "description": "Disable cross-shard queries for this user.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "database": { "description": "Name of the database cluster this user belongs to. This refers to `name` setting in [`pgdog.toml`](https://docs.pgdog.dev/configuration/pgdog.toml/databases/), databases section.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#database", @@ -114,19 +116,13 @@ }, "idle_timeout": { "description": "Overrides [`idle_timeout`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#idle_timeout) for this user. Server connections that have been idle for this long, without affecting [`min_pool_size`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#min_pool_size), will be closed.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#idle_timeout", - "type": [ - "integer", - "null" - ], + "type": ["integer", "null"], "format": "uint64", "minimum": 0 }, "min_pool_size": { "description": "Overrides [`min_pool_size`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#min_pool_size) for this user. Opens at least this many connections on pooler startup and keeps them open despite [`idle_timeout`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#idle_timeout).\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#min_pool_size", - "type": [ - "integer", - "null" - ], + "type": ["integer", "null"], "format": "uint", "minimum": 0 }, @@ -136,10 +132,7 @@ }, "password": { "description": "The password for the user. Clients will need to provide this when connecting to PgDog.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#password", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "passwords": { "description": "Multiple passwords for this user, all of which will be attempted during auth to server and client.", @@ -151,10 +144,7 @@ }, "pool_size": { "description": "Overrides [`default_pool_size`](https://docs.pgdog.dev/configuration/pgdog.toml/general/) for this user. No more than this many server connections will be open at any given time to serve requests for this connection pool.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#pool_size", - "type": [ - "integer", - "null" - ], + "type": ["integer", "null"], "format": "uint", "minimum": 0 }, @@ -171,10 +161,7 @@ }, "read_only": { "description": "Sets `default_transaction_read_only` to `on` for all connections.", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "replication_mode": { "description": "Sets the `replication=database` parameter on user connections to Postgres. Allows this user to use replication commands.\n\n_Default:_ `false`\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#replication_mode", @@ -183,10 +170,7 @@ }, "replication_sharding": { "description": "Sharding target database for replication.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "schema_admin": { "description": "Schema owner with elevated DDL privileges.", @@ -200,62 +184,39 @@ }, "server_iam_region": { "description": "Optional region override for RDS IAM token generation.", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "server_lifetime": { "description": "Server connections older than this (in milliseconds) will be closed when returned to the pool.", - "type": [ - "integer", - "null" - ], + "type": ["integer", "null"], "format": "uint64", "minimum": 0 }, "server_password": { "description": "Which password to connect with when creating backend connections from PgDog to PostgreSQL. By default, the password configured in `password` is used. This setting allows you to override this configuration and use a different password, decoupling server passwords from user passwords given to clients.\n\n**Note:** Values specified in `pgdog.toml` take priority over this configuration.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#server_password", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "server_user": { "description": "Which user to connect with when creating backend connections from PgDog to PostgreSQL. By default, the user configured in `name` is used. This setting allows you to override this configuration and use a different user.\n\n**Note:** Values specified in `pgdog.toml` take priority over this configuration.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#server_user", - "type": [ - "string", - "null" - ] + "type": ["string", "null"] }, "statement_timeout": { "description": "Statement timeout.\n\nSets the `statement_timeout` on all server connections at connection creation. This allows you to set a reasonable default for each user without modifying `postgresql.conf` or using `ALTER USER`.\n\n**Note:** Nothing is preventing the user from manually changing this setting at runtime, e.g., by running `SET statement_timeout TO 0`;\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#statement_timeout", - "type": [ - "integer", - "null" - ], + "type": ["integer", "null"], "format": "uint64", "minimum": 0 }, "two_phase_commit": { "description": "Overrides [`two_phase_commit`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#two_phase_commit) for this user.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#two_phase_commit", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] }, "two_phase_commit_auto": { "description": "Overrides [`two_phase_commit_auto`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#two_phase_commit_auto) for this user.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#two_phase_commit_auto", - "type": [ - "boolean", - "null" - ] + "type": ["boolean", "null"] } }, "additionalProperties": false, - "required": [ - "name" - ] + "required": ["name"] } } -} \ No newline at end of file +} From 517383137e1e9b98144a3548b1601ba674ca12af Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 19:45:40 +0200 Subject: [PATCH 07/15] fix: bad format --- .schema/users.schema.json | 76 ++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/.schema/users.schema.json b/.schema/users.schema.json index 668860b41..7adbc2929 100644 --- a/.schema/users.schema.json +++ b/.schema/users.schema.json @@ -99,7 +99,10 @@ }, "cross_shard_disabled": { "description": "Disable cross-shard queries for this user.", - "type": ["boolean", "null"] + "type": [ + "boolean", + "null" + ] }, "database": { "description": "Name of the database cluster this user belongs to. This refers to `name` setting in [`pgdog.toml`](https://docs.pgdog.dev/configuration/pgdog.toml/databases/), databases section.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#database", @@ -116,13 +119,19 @@ }, "idle_timeout": { "description": "Overrides [`idle_timeout`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#idle_timeout) for this user. Server connections that have been idle for this long, without affecting [`min_pool_size`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#min_pool_size), will be closed.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#idle_timeout", - "type": ["integer", "null"], + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0 }, "min_pool_size": { "description": "Overrides [`min_pool_size`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#min_pool_size) for this user. Opens at least this many connections on pooler startup and keeps them open despite [`idle_timeout`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#idle_timeout).\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#min_pool_size", - "type": ["integer", "null"], + "type": [ + "integer", + "null" + ], "format": "uint", "minimum": 0 }, @@ -132,7 +141,10 @@ }, "password": { "description": "The password for the user. Clients will need to provide this when connecting to PgDog.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#password", - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "passwords": { "description": "Multiple passwords for this user, all of which will be attempted during auth to server and client.", @@ -144,7 +156,10 @@ }, "pool_size": { "description": "Overrides [`default_pool_size`](https://docs.pgdog.dev/configuration/pgdog.toml/general/) for this user. No more than this many server connections will be open at any given time to serve requests for this connection pool.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#pool_size", - "type": ["integer", "null"], + "type": [ + "integer", + "null" + ], "format": "uint", "minimum": 0 }, @@ -161,7 +176,10 @@ }, "read_only": { "description": "Sets `default_transaction_read_only` to `on` for all connections.", - "type": ["boolean", "null"] + "type": [ + "boolean", + "null" + ] }, "replication_mode": { "description": "Sets the `replication=database` parameter on user connections to Postgres. Allows this user to use replication commands.\n\n_Default:_ `false`\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#replication_mode", @@ -170,7 +188,10 @@ }, "replication_sharding": { "description": "Sharding target database for replication.", - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "schema_admin": { "description": "Schema owner with elevated DDL privileges.", @@ -184,39 +205,62 @@ }, "server_iam_region": { "description": "Optional region override for RDS IAM token generation.", - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "server_lifetime": { "description": "Server connections older than this (in milliseconds) will be closed when returned to the pool.", - "type": ["integer", "null"], + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0 }, "server_password": { "description": "Which password to connect with when creating backend connections from PgDog to PostgreSQL. By default, the password configured in `password` is used. This setting allows you to override this configuration and use a different password, decoupling server passwords from user passwords given to clients.\n\n**Note:** Values specified in `pgdog.toml` take priority over this configuration.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#server_password", - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "server_user": { "description": "Which user to connect with when creating backend connections from PgDog to PostgreSQL. By default, the user configured in `name` is used. This setting allows you to override this configuration and use a different user.\n\n**Note:** Values specified in `pgdog.toml` take priority over this configuration.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#server_user", - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "statement_timeout": { "description": "Statement timeout.\n\nSets the `statement_timeout` on all server connections at connection creation. This allows you to set a reasonable default for each user without modifying `postgresql.conf` or using `ALTER USER`.\n\n**Note:** Nothing is preventing the user from manually changing this setting at runtime, e.g., by running `SET statement_timeout TO 0`;\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#statement_timeout", - "type": ["integer", "null"], + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0 }, "two_phase_commit": { "description": "Overrides [`two_phase_commit`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#two_phase_commit) for this user.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#two_phase_commit", - "type": ["boolean", "null"] + "type": [ + "boolean", + "null" + ] }, "two_phase_commit_auto": { "description": "Overrides [`two_phase_commit_auto`](https://docs.pgdog.dev/configuration/pgdog.toml/general/#two_phase_commit_auto) for this user.\n\nhttps://docs.pgdog.dev/configuration/users.toml/users/#two_phase_commit_auto", - "type": ["boolean", "null"] + "type": [ + "boolean", + "null" + ] } }, "additionalProperties": false, - "required": ["name"] + "required": [ + "name" + ] } } -} +} \ No newline at end of file From 074e017ab30ee052c642473e6fcbbd0e76321a66 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 19:52:33 +0200 Subject: [PATCH 08/15] fix: just realized the description is based on the comment --- pgdog-config/src/users.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pgdog-config/src/users.rs b/pgdog-config/src/users.rs index fe6e300a5..ee0ad80a9 100644 --- a/pgdog-config/src/users.rs +++ b/pgdog-config/src/users.rs @@ -135,6 +135,7 @@ pub enum ServerAuth { Password, /// Generate an AWS RDS IAM auth token per connection attempt. RdsIam, + /// Generate an Azure Workload Identity auth token per connection attempt. AzureWorkloadIdentity, } From af71bfe1d86447fdfb2f4bcc2af84d4a740b4b4e Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 19:54:17 +0200 Subject: [PATCH 09/15] fix: tests --- pgdog/src/backend/auth/azure_workload_identity.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pgdog/src/backend/auth/azure_workload_identity.rs b/pgdog/src/backend/auth/azure_workload_identity.rs index 5169dcf0e..48201bb0f 100644 --- a/pgdog/src/backend/auth/azure_workload_identity.rs +++ b/pgdog/src/backend/auth/azure_workload_identity.rs @@ -35,6 +35,11 @@ fn test_token_override() -> Option { TEST_TOKEN_OVERRIDE.lock().clone() } +#[cfg(test)] +pub(crate) fn set_test_token_override(token: Option) { + *TEST_TOKEN_OVERRIDE.lock() = token; +} + #[cfg(test)] static TEST_TOKEN_OVERRIDE: once_cell::sync::Lazy>> = once_cell::sync::Lazy::new(|| parking_lot::Mutex::new(None)); From 9f4241feaedfb1b93e5c0d744f28ecb0ed3bc146 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 20:14:16 +0200 Subject: [PATCH 10/15] refactor: cleanup redundant code --- pgdog-config/src/core.rs | 6 ++---- pgdog-config/src/users.rs | 12 ++++++------ pgdog/src/backend/pool/address.rs | 4 +--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/pgdog-config/src/core.rs b/pgdog-config/src/core.rs index 62564d76a..f578cfdb4 100644 --- a/pgdog-config/src/core.rs +++ b/pgdog-config/src/core.rs @@ -21,7 +21,7 @@ use super::pooling::PoolerMode; use super::replication::{MirrorConfig, Mirroring, MirroringLevel, ReplicaLag, Replication}; use super::rewrite::Rewrite; use super::sharding::{ManualQuery, OmnishardedTables, ShardedMapping, ShardedTable}; -use super::users::{Admin, Plugin, ServerAuth, Users}; +use super::users::{Admin, Plugin, Users}; #[derive(Debug, Clone, PartialEq)] pub struct ConfigAndUsers { @@ -112,9 +112,7 @@ impl ConfigAndUsers { } fn validate_server_auth(&self) -> Result<(), Error> { - let is_external_identity = self.users.users.iter().any(|user| { - [ServerAuth::RdsIam, ServerAuth::AzureWorkloadIdentity].contains(&user.server_auth) - }); + let is_external_identity = self.users.users.iter().any(|user| user.is_external_identity()); if !is_external_identity { return Ok(()); diff --git a/pgdog-config/src/users.rs b/pgdog-config/src/users.rs index ee0ad80a9..0488da033 100644 --- a/pgdog-config/src/users.rs +++ b/pgdog-config/src/users.rs @@ -140,12 +140,8 @@ pub enum ServerAuth { } impl ServerAuth { - pub fn rds_iam(&self) -> bool { - matches!(self, Self::RdsIam) - } - - pub fn azure_workload_identity(&self) -> bool { - matches!(self, Self::AzureWorkloadIdentity) + pub fn is_external_identity(&self) -> bool { + matches!(self, Self::RdsIam | Self::AzureWorkloadIdentity) } } @@ -276,6 +272,10 @@ impl User { ..Default::default() } } + + pub fn is_external_identity(&self) -> bool { + self.server_auth.is_external_identity() + } } /// Admin database settings control access to the [admin](https://docs.pgdog.dev/administration/) database which contains real time statistics about internal operations of PgDog. diff --git a/pgdog/src/backend/pool/address.rs b/pgdog/src/backend/pool/address.rs index c8a7a2218..b33e1a81e 100644 --- a/pgdog/src/backend/pool/address.rs +++ b/pgdog/src/backend/pool/address.rs @@ -64,9 +64,7 @@ impl Address { } else { user.name.clone() }, - passwords: if server_auth.rds_iam() { - vec![] - } else if server_auth.azure_workload_identity() { + passwords: if server_auth.is_external_identity() { vec![] } else if let Some(password) = database.password.clone() { vec![password] From b8c9e0374eb934cfbee2206cc5d02d81ecabd563 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 20:15:38 +0200 Subject: [PATCH 11/15] fix: missing use --- pgdog-config/src/core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgdog-config/src/core.rs b/pgdog-config/src/core.rs index f578cfdb4..26fd544d1 100644 --- a/pgdog-config/src/core.rs +++ b/pgdog-config/src/core.rs @@ -652,7 +652,7 @@ impl Config { #[cfg(test)] mod tests { use super::*; - use crate::{PoolerMode, PreparedStatements}; + use crate::{PoolerMode, PreparedStatements, ServerAuth}; use std::time::Duration; #[test] From 00f5c8b471508d975019ba7c918fe921facb2a6f Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 20:26:23 +0200 Subject: [PATCH 12/15] feat: adding some test cases --- pgdog-config/src/core.rs | 36 ++++++++++++++ .../backend/auth/azure_workload_identity.rs | 3 -- pgdog/src/backend/pool/address.rs | 47 +++++++++++++++++++ pgdog/src/backend/schema/sync/pg_dump.rs | 15 ++++++ pgdog/src/backend/server.rs | 2 +- 5 files changed, 99 insertions(+), 4 deletions(-) diff --git a/pgdog-config/src/core.rs b/pgdog-config/src/core.rs index 26fd544d1..53d2428af 100644 --- a/pgdog-config/src/core.rs +++ b/pgdog-config/src/core.rs @@ -1321,4 +1321,40 @@ shard = 0 assert!(err.contains("tls_verify")); assert!(err.contains("rds_iam")); } + + #[test] + fn test_azure_workload_identity_rejects_passthrough_auth() { + let mut config = ConfigAndUsers::default(); + config.config.general.passthrough_auth = PassthroughAuth::EnabledPlain; + config.config.general.tls_verify = TlsVerifyMode::VerifyFull; + config.users.users.push(crate::User { + name: "alice".into(), + database: "db".into(), + password: Some("secret".into()), + server_auth: ServerAuth::AzureWorkloadIdentity, + ..Default::default() + }); + + let err = config.check().unwrap_err().to_string(); + assert!(err.contains("passthrough_auth")); + assert!(err.contains("azure_workload_identity")); + } + + #[test] + fn test_azure_workload_identity_rejects_tls_verify_disabled() { + let mut config = ConfigAndUsers::default(); + config.config.general.tls_verify = TlsVerifyMode::Disabled; + config.config.general.passthrough_auth = PassthroughAuth::Disabled; + config.users.users.push(crate::User { + name: "alice".into(), + database: "db".into(), + password: Some("secret".into()), + server_auth: ServerAuth::AzureWorkloadIdentity, + ..Default::default() + }); + + let err = config.check().unwrap_err().to_string(); + assert!(err.contains("tls_verify")); + assert!(err.contains("azure_workload_identity")); + } } diff --git a/pgdog/src/backend/auth/azure_workload_identity.rs b/pgdog/src/backend/auth/azure_workload_identity.rs index 48201bb0f..d6ba19e03 100644 --- a/pgdog/src/backend/auth/azure_workload_identity.rs +++ b/pgdog/src/backend/auth/azure_workload_identity.rs @@ -94,9 +94,6 @@ mod tests { }; let token = token(&addr).await.unwrap(); - assert!(token.starts_with( - "my-awesome-db.postgres.database.azure.com:5432/?Action=connect&DBUser=db_user" - )); assert!(token.contains("https://sts.windows.net/")); assert!(token.contains("https://management.azure.com")); assert!(token.contains("appid")); diff --git a/pgdog/src/backend/pool/address.rs b/pgdog/src/backend/pool/address.rs index b33e1a81e..deef782c8 100644 --- a/pgdog/src/backend/pool/address.rs +++ b/pgdog/src/backend/pool/address.rs @@ -221,6 +221,34 @@ mod test { assert_eq!(address.server_iam_region.as_deref(), Some("us-east-1")); } + #[test] + fn test_azure_workload_identity_does_not_use_static_password() { + let database = Database { + name: "pgdog".into(), + host: "127.0.0.1".into(), + port: 6432, + password: Some("db-level-pass".into()), + ..Default::default() + }; + + let user = User { + name: "pgdog".into(), + password: Some("user-pass".into()), + server_password: Some("server-pass".into()), + server_auth: ServerAuth::AzureWorkloadIdentity, + server_iam_region: None, + database: "pgdog".into(), + ..Default::default() + }; + + let address = Address::new(&database, &user, 0); + assert!( + address.passwords.is_empty(), + "RDS IAM addresses must not carry static passwords" + ); + assert_eq!(address.server_auth, ServerAuth::AzureWorkloadIdentity); + } + #[test] fn test_addr_from_url() { let addr = @@ -258,6 +286,25 @@ mod test { .to_string(); crate::backend::auth::rds_iam::set_test_token_override(None); + assert_eq!(secret, "token-from-iam"); + } + + #[tokio::test] + async fn test_auth_secret_azure_workload_identity_mode_uses_generator() { + let mut addr = Address::new_test(); + addr.server_auth = ServerAuth::AzureWorkloadIdentity; + addr.passwords = vec!["wrong".into()]; + + crate::backend::auth::azure_workload_identity::set_test_token_override(Some("token-from-iam".into())); + let secret = addr + .auth_secrets() + .await + .unwrap() + .first() + .unwrap() + .to_string(); + crate::backend::auth::azure_workload_identity::set_test_token_override(None); + assert_eq!(secret, "token-from-iam"); } } diff --git a/pgdog/src/backend/schema/sync/pg_dump.rs b/pgdog/src/backend/schema/sync/pg_dump.rs index 39be2242f..08d5fa599 100644 --- a/pgdog/src/backend/schema/sync/pg_dump.rs +++ b/pgdog/src/backend/schema/sync/pg_dump.rs @@ -1183,6 +1183,21 @@ mod test { assert_eq!(sslmode, Some(OsStr::new("require"))); } + #[test] + fn test_build_pg_dump_command_sets_tls_for_azure_workload_identity() { + let mut addr = backend::pool::Address::new_test(); + addr.server_auth = ServerAuth::AzureWorkloadIdentity; + let command = build_pg_dump_command("pg_dump", &addr, "token"); + + let sslmode = command + .as_std() + .get_envs() + .find(|(key, _)| *key == OsStr::new("PGSSLMODE")) + .and_then(|(_, value)| value); + + assert_eq!(sslmode, Some(OsStr::new("require"))); + } + #[test] fn test_specific_dump() { let dump = r#" diff --git a/pgdog/src/backend/server.rs b/pgdog/src/backend/server.rs index 8393829af..5b2c7e09c 100644 --- a/pgdog/src/backend/server.rs +++ b/pgdog/src/backend/server.rs @@ -1241,7 +1241,7 @@ pub mod test { } #[tokio::test] - async fn test_connect_azure_sql_workload_identity_uses_dynamic_token_not_static_password() { + async fn test_connect_azure_workload_identity_uses_dynamic_token_not_static_password() { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let port = listener.local_addr().unwrap().port(); let expected_secret = "token-for-test".to_string(); From 7909fe772132eee8e1bc67c21fe918946a9cbbe7 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 20:31:12 +0200 Subject: [PATCH 13/15] format: cargo fmt --- pgdog-config/src/core.rs | 8 ++++++-- pgdog/src/backend/pool/address.rs | 8 +++++--- pgdog/src/backend/schema/sync/pg_dump.rs | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pgdog-config/src/core.rs b/pgdog-config/src/core.rs index 53d2428af..e23155536 100644 --- a/pgdog-config/src/core.rs +++ b/pgdog-config/src/core.rs @@ -112,7 +112,11 @@ impl ConfigAndUsers { } fn validate_server_auth(&self) -> Result<(), Error> { - let is_external_identity = self.users.users.iter().any(|user| user.is_external_identity()); + let is_external_identity = self + .users + .users + .iter() + .any(|user| user.is_external_identity()); if !is_external_identity { return Ok(()); @@ -1322,7 +1326,7 @@ shard = 0 assert!(err.contains("rds_iam")); } - #[test] + #[test] fn test_azure_workload_identity_rejects_passthrough_auth() { let mut config = ConfigAndUsers::default(); config.config.general.passthrough_auth = PassthroughAuth::EnabledPlain; diff --git a/pgdog/src/backend/pool/address.rs b/pgdog/src/backend/pool/address.rs index deef782c8..8d0fd5e4c 100644 --- a/pgdog/src/backend/pool/address.rs +++ b/pgdog/src/backend/pool/address.rs @@ -221,7 +221,7 @@ mod test { assert_eq!(address.server_iam_region.as_deref(), Some("us-east-1")); } - #[test] + #[test] fn test_azure_workload_identity_does_not_use_static_password() { let database = Database { name: "pgdog".into(), @@ -289,13 +289,15 @@ mod test { assert_eq!(secret, "token-from-iam"); } - #[tokio::test] + #[tokio::test] async fn test_auth_secret_azure_workload_identity_mode_uses_generator() { let mut addr = Address::new_test(); addr.server_auth = ServerAuth::AzureWorkloadIdentity; addr.passwords = vec!["wrong".into()]; - crate::backend::auth::azure_workload_identity::set_test_token_override(Some("token-from-iam".into())); + crate::backend::auth::azure_workload_identity::set_test_token_override(Some( + "token-from-iam".into(), + )); let secret = addr .auth_secrets() .await diff --git a/pgdog/src/backend/schema/sync/pg_dump.rs b/pgdog/src/backend/schema/sync/pg_dump.rs index 08d5fa599..7682dda56 100644 --- a/pgdog/src/backend/schema/sync/pg_dump.rs +++ b/pgdog/src/backend/schema/sync/pg_dump.rs @@ -1183,7 +1183,7 @@ mod test { assert_eq!(sslmode, Some(OsStr::new("require"))); } - #[test] + #[test] fn test_build_pg_dump_command_sets_tls_for_azure_workload_identity() { let mut addr = backend::pool::Address::new_test(); addr.server_auth = ServerAuth::AzureWorkloadIdentity; From 151279056e3e56cd3aaeef0b8566d509b4706722 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 21:33:52 +0200 Subject: [PATCH 14/15] fix: pgdump command sets PGSSLMODE to require --- pgdog/src/backend/schema/sync/pg_dump.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgdog/src/backend/schema/sync/pg_dump.rs b/pgdog/src/backend/schema/sync/pg_dump.rs index 7682dda56..cd3bd5148 100644 --- a/pgdog/src/backend/schema/sync/pg_dump.rs +++ b/pgdog/src/backend/schema/sync/pg_dump.rs @@ -138,7 +138,7 @@ fn build_pg_dump_command( .arg("-d") .arg(&addr.database_name); - if addr.server_auth == ServerAuth::RdsIam { + if addr.server_auth.is_external_identity() { command.env("PGSSLMODE", "require"); } From a2249bf538411b62b6749548f9aa7cfc8c3c4ce5 Mon Sep 17 00:00:00 2001 From: Abdessalam ZAIMI Date: Thu, 16 Apr 2026 23:07:55 +0200 Subject: [PATCH 15/15] fix: ignoring test_token_contains_expected_query_fields for now --- .../backend/auth/azure_workload_identity.rs | 18 +++++++++++++++--- pgdog/src/backend/schema/sync/pg_dump.rs | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pgdog/src/backend/auth/azure_workload_identity.rs b/pgdog/src/backend/auth/azure_workload_identity.rs index d6ba19e03..dc59e1620 100644 --- a/pgdog/src/backend/auth/azure_workload_identity.rs +++ b/pgdog/src/backend/auth/azure_workload_identity.rs @@ -46,10 +46,10 @@ static TEST_TOKEN_OVERRIDE: once_cell::sync::Lazy> to Result, E> + .and_then(|bytes| String::from_utf8(bytes).ok()) + .expect("Failed to parse JWT payload as valid UTF-8 JSON"); + assert!(token.contains("https://sts.windows.net/")); assert!(token.contains("https://management.azure.com")); assert!(token.contains("appid")); diff --git a/pgdog/src/backend/schema/sync/pg_dump.rs b/pgdog/src/backend/schema/sync/pg_dump.rs index cd3bd5148..f03d06f50 100644 --- a/pgdog/src/backend/schema/sync/pg_dump.rs +++ b/pgdog/src/backend/schema/sync/pg_dump.rs @@ -25,7 +25,7 @@ use crate::{ replication::{publisher::PublicationTable, status::SchemaStatement}, Cluster, }, - config::{config, ServerAuth}, + config::config, frontend::router::parser::{sequence::Sequence, Column, Table}, };