20230614 unix account security - move account name deny to unixd (#1733)

This commit is contained in:
Firstyear 2023-06-15 13:24:53 +10:00 committed by GitHub
parent 76cee8cecb
commit a77a7aa2a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 775 additions and 185 deletions

390
Cargo.lock generated
View file

@ -68,7 +68,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"once_cell",
"version_check",
]
@ -86,13 +86,19 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e"
[[package]]
name = "android-tzdata"
version = "0.1.1"
@ -151,7 +157,7 @@ dependencies = [
"num-traits",
"rusticata-macros",
"thiserror",
"time 0.3.21",
"time 0.3.22",
]
[[package]]
@ -566,9 +572,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.3.1"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84"
checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
[[package]]
name = "blake3"
@ -936,7 +942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [
"percent-encoding",
"time 0.3.21",
"time 0.3.22",
"version_check",
]
@ -952,7 +958,7 @@ dependencies = [
"publicsuffix",
"serde",
"serde_json",
"time 0.3.21",
"time 0.3.22",
"url",
]
@ -1080,14 +1086,14 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.14"
version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"crossbeam-utils",
"memoffset 0.8.0",
"memoffset 0.9.0",
"scopeguard",
]
@ -1103,9 +1109,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if 1.0.0",
]
@ -1161,16 +1167,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "ctor"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "ctr"
version = "0.6.0"
@ -1504,11 +1500,20 @@ checksum = "3364d69f691f3903b1a71605fa04f40a7c2d259f0f0512347e36d19a63debf1f"
dependencies = [
"base64 0.21.2",
"byteorder",
"getrandom 0.2.9",
"getrandom 0.2.10",
"openssl",
"zeroize",
]
[[package]]
name = "file-id"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13be71e6ca82e91bc0cb862bebaac0b2d1924a5a1d970c822b2f98b63fda8c3"
dependencies = [
"winapi-util",
]
[[package]]
name = "filetime"
version = "0.2.21"
@ -1571,6 +1576,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]]
name = "futures"
version = "0.3.28"
@ -1718,9 +1732,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@ -1973,12 +1987,22 @@ dependencies = [
]
[[package]]
name = "hashlink"
version = "0.8.2"
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
dependencies = [
"hashbrown 0.13.2",
"ahash 0.8.3",
"allocator-api2",
]
[[package]]
name = "hashlink"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f"
dependencies = [
"hashbrown 0.14.0",
]
[[package]]
@ -2154,9 +2178,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.56"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@ -2262,6 +2286,26 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac"
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags 1.3.2",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -2314,9 +2358,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.63"
version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [
"wasm-bindgen",
]
@ -2377,7 +2421,7 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
"time 0.3.21",
"time 0.3.22",
"tokio",
"toml",
"tracing",
@ -2421,7 +2465,7 @@ dependencies = [
"scim_proto",
"serde",
"serde_json",
"time 0.3.21",
"time 0.3.22",
"tracing",
"url",
"urlencoding",
@ -2447,7 +2491,7 @@ dependencies = [
"serde",
"serde_json",
"shellexpand",
"time 0.3.21",
"time 0.3.22",
"tokio",
"tracing",
"tracing-subscriber",
@ -2464,6 +2508,7 @@ dependencies = [
"bytes",
"clap",
"clap_complete",
"csv",
"futures",
"kanidm_client",
"kanidm_lib_crypto",
@ -2473,6 +2518,7 @@ dependencies = [
"libc",
"libsqlite3-sys",
"lru 0.8.1",
"notify-debouncer-full",
"profiles",
"r2d2",
"r2d2_sqlite",
@ -2515,7 +2561,7 @@ dependencies = [
"tide",
"tide-compress",
"tide-openssl",
"time 0.3.21",
"time 0.3.22",
"tokio",
"tokio-openssl",
"tokio-util",
@ -2567,7 +2613,7 @@ dependencies = [
"smolset",
"sshkeys",
"tide",
"time 0.3.21",
"time 0.3.22",
"tokio",
"tokio-util",
"toml",
@ -2609,7 +2655,7 @@ dependencies = [
"serde_json",
"sketching",
"testkit-macros",
"time 0.3.21",
"time 0.3.22",
"tokio",
"tracing",
"url",
@ -2629,7 +2675,7 @@ dependencies = [
"serde",
"serde-wasm-bindgen",
"serde_json",
"time 0.3.21",
"time 0.3.22",
"url",
"uuid",
"wasm-bindgen",
@ -2640,6 +2686,26 @@ dependencies = [
"yew-router",
]
[[package]]
name = "kqueue"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags 1.3.2",
"libc",
]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
@ -2672,9 +2738,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lber"
version = "0.4.0"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5d85f5e00e12cb50c70c3b1c1f0daff6546eb4c608b44d0a990e38a539e0446"
checksum = "2df7f9fd9f64cf8f59e1a4a0753fe7d575a5b38d3d7ac5758dcee9357d83ef0a"
dependencies = [
"bytes",
"nom",
@ -2822,9 +2888,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "lock_api"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
@ -2832,11 +2898,10 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
dependencies = [
"cfg-if 1.0.0",
"serde",
"value-bag",
]
@ -2900,9 +2965,9 @@ dependencies = [
[[package]]
name = "memoffset"
version = "0.8.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
@ -2930,14 +2995,14 @@ dependencies = [
[[package]]
name = "mio"
version = "0.8.6"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@ -2977,6 +3042,37 @@ dependencies = [
"serde",
]
[[package]]
name = "notify"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d9ba6c734de18ca27c8cef5cd7058aa4ac9f63596131e4c7e41e579319032a2"
dependencies = [
"bitflags 1.3.2",
"crossbeam-channel",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"mio",
"walkdir",
"windows-sys 0.45.0",
]
[[package]]
name = "notify-debouncer-full"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4812c1eb49be776fb8df4961623bdc01ec9dfdc1abe8211ceb09150a2e64219"
dependencies = [
"crossbeam-channel",
"file-id",
"notify",
"parking_lot",
"walkdir",
]
[[package]]
name = "nss_kanidm"
version = "1.1.0-beta.13-dev"
@ -3092,13 +3188,13 @@ dependencies = [
[[package]]
name = "oauth2"
version = "4.4.0"
version = "4.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50df55a3cc0374df91ef8da8741542d9e0b9e6581481ed1cffe84f64d2f5fc3d"
checksum = "09a6e2a2b13a56ebeabba9142f911745be6456163fd6c3d361274ebcd891a80c"
dependencies = [
"base64 0.13.1",
"chrono",
"getrandom 0.2.9",
"getrandom 0.2.10",
"http",
"rand 0.8.5",
"serde",
@ -3120,9 +3216,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.17.1"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "oorandom"
@ -3216,9 +3312,9 @@ dependencies = [
[[package]]
name = "os_str_bytes"
version = "6.5.0"
version = "6.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac"
[[package]]
name = "overload"
@ -3253,15 +3349,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.7"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall 0.2.16",
"redox_syscall 0.3.5",
"smallvec",
"windows-sys 0.45.0",
"windows-targets 0.48.0",
]
[[package]]
@ -3660,7 +3756,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
]
[[package]]
@ -3718,7 +3814,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"redox_syscall 0.2.16",
"thiserror",
]
@ -3891,9 +3987,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.37.19"
version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
dependencies = [
"bitflags 1.3.2",
"errno",
@ -3952,7 +4048,7 @@ dependencies = [
"peg",
"serde",
"serde_json",
"time 0.3.21",
"time 0.3.22",
"tracing",
"tracing-subscriber",
"url",
@ -4000,7 +4096,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b5ff8f655381fc80f470384da0a461b19b7bf18d685639ccf6df0abd3d2363d"
dependencies = [
"bitflags 2.3.1",
"bitflags 2.3.2",
"libc",
"once_cell",
"reference-counted-singleton",
@ -4010,9 +4106,9 @@ dependencies = [
[[package]]
name = "selinux-sys"
version = "0.6.4"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f37ccfd0557caec11f117e6d6103aaa217d1aad80cfb6ee3d0e1af5b568a1d9"
checksum = "f2b8dbf5dd0b21d466538786194081b2c4d61878e1427f7e52f99d5845432483"
dependencies = [
"bindgen",
"cc",
@ -4412,11 +4508,70 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "sval"
version = "1.0.0-alpha.5"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08"
checksum = "e2faba619276044eec7cd160d87b15d9191fb9b9f7198440343d2144f760cf08"
[[package]]
name = "sval_buffer"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a353d3cca10721384077c9643c3fafdd6ed2600e57933b8e45c0b580d97b25af"
dependencies = [
"sval",
"sval_ref",
]
[[package]]
name = "sval_dynamic"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee5fc7349e9f6cb2ab950046818f66ad3f2d7209ccc5dced93da19292a30273a"
dependencies = [
"sval",
]
[[package]]
name = "sval_fmt"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "098fb51d5d6007bd2c3f0a23b79aa953d7c46bf943086ce51424c3187c40f9b1"
dependencies = [
"itoa",
"ryu",
"sval",
]
[[package]]
name = "sval_json"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f01126a2783d767496f18f13af26ab2587881f6343368bb26dc62956a723d1c7"
dependencies = [
"itoa",
"ryu",
"sval",
]
[[package]]
name = "sval_ref"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5854d9eaa7bd31840a850322591c59c5b547eb29c9a6ecee1989d6ef963312ce"
dependencies = [
"sval",
]
[[package]]
name = "sval_serde"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cdd25fc04c5e882787d62112591aa93efb5bdc2000b43164d29f08582bb85f7"
dependencies = [
"serde",
"sval",
"sval_buffer",
"sval_fmt",
]
[[package]]
@ -4455,15 +4610,16 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.5.0"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"fastrand",
"redox_syscall 0.3.5",
"rustix",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@ -4620,9 +4776,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.21"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
dependencies = [
"itoa",
"libc",
@ -4972,11 +5128,11 @@ dependencies = [
[[package]]
name = "uuid"
version = "1.3.3"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"serde",
]
@ -4988,16 +5144,38 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "value-bag"
version = "1.0.0-alpha.9"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e"
dependencies = [
"value-bag-serde1",
"value-bag-sval2",
]
[[package]]
name = "value-bag-serde1"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4735c95b4cca1447b448e2e2e87e98d7e7498f4da27e355cf7af02204521001d"
dependencies = [
"ctor",
"erased-serde",
"serde",
"serde_fmt",
]
[[package]]
name = "value-bag-sval2"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859cb4f0ce7da6a118b559ba74b0e63bf569bea867c20ba457a6b1c886a04e97"
dependencies = [
"sval",
"version_check",
"sval_buffer",
"sval_dynamic",
"sval_fmt",
"sval_json",
"sval_ref",
"sval_serde",
]
[[package]]
@ -5058,9 +5236,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.86"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [
"cfg-if 1.0.0",
"serde",
@ -5070,9 +5248,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.86"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [
"bumpalo",
"log",
@ -5085,9 +5263,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.36"
version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@ -5097,9 +5275,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.86"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -5107,9 +5285,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.86"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
@ -5120,15 +5298,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.86"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.36"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e636f3a428ff62b3742ebc3c70e254dfe12b8c2b469d688ea59cdd4abcf502"
checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671"
dependencies = [
"console_error_panic_hook",
"js-sys",
@ -5140,9 +5318,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.36"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f18c1fad2f7c4958e7bcce014fa212f59a65d5e3721d0f77e6c0b27ede936ba3"
checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575"
dependencies = [
"proc-macro2",
"quote",
@ -5150,9 +5328,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.63"
version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -5531,7 +5709,7 @@ dependencies = [
"oid-registry",
"rusticata-macros",
"thiserror",
"time 0.3.21",
"time 0.3.22",
]
[[package]]
@ -5636,5 +5814,5 @@ dependencies = [
"lazy_static",
"quick-error",
"regex",
"time 0.3.21",
"time 0.3.22",
]

View file

@ -99,6 +99,7 @@ libnss = "^0.4.0"
libsqlite3-sys = "^0.25.0"
lru = "^0.8.0"
mathru = "^0.13.0"
notify-debouncer-full = { version = "0.1" }
num_enum = "^0.5.11"
oauth2_ext = { version = "^4.1.0", package = "oauth2", default-features = false }
openssl-sys = "^0.9"

View file

@ -56,6 +56,7 @@ use_etc_skel = false
uid_attr_map = "spn"
gid_attr_map = "spn"
selinux = true
allow_local_account_override = ["account_name"]
```
`pam_allowed_login_groups` defines a set of POSIX groups where membership of any of these groups
@ -96,6 +97,12 @@ setting as no bearing on systems without SELinux, as these features will automat
if SELinux is not detected when the daemon starts. Note that `kanidm_unixd_tasks` must also be built
with the SELinux feature flag for this functionality. Defaults to true.
`allow_local_account_override` allows kanidm to "override" the content of a user or group that is
defined locally. By default kanidm will detect when a user/group conflict with their entries from
`/etc/passwd` or `/etc/group` and will ignore the kanidm entry. However if you want kanidm to
override users or groups from the local system, you must list them in this field. Note that this can
have many unexpected consequences, so it is not recommended to enable this.
You can then check the communication status of the daemon:
```bash

View file

@ -8,3 +8,5 @@
# use_etc_skel = false
# uid_attr_map = "spn"
# gid_attr_map = "spn"
# allow_local_account_override = ["admin"]

View file

@ -42,17 +42,10 @@ lazy_static! {
};
pub static ref DISALLOWED_NAMES: HashSet<&'static str> = {
let mut m = HashSet::with_capacity(16);
// Most of these were removed in favour of the unixd daemon filtering out
// local users instead.
let mut m = HashSet::with_capacity(2);
m.insert("root");
m.insert("nobody");
m.insert("nogroup");
m.insert("wheel");
m.insert("sshd");
m.insert("shadow");
m.insert("systemd");
m.insert("mail");
m.insert("man");
m.insert("administrator");
m.insert("dn=token");
m
};

View file

@ -43,6 +43,7 @@ path = "src/lib.rs"
[dependencies]
bytes.workspace = true
clap = { workspace = true, features = ["derive", "env"] }
csv.workspace = true
futures.workspace = true
libc.workspace = true
libsqlite3-sys.workspace = true
@ -51,7 +52,7 @@ kanidm_client.workspace = true
kanidm_proto.workspace = true
kanidm_lib_crypto.workspace = true
kanidm_lib_file_permissions.workspace = true
notify-debouncer-full.workspace = true
r2d2.workspace = true
r2d2_sqlite.workspace = true
rpassword.workspace = true
@ -62,7 +63,7 @@ serde_json.workspace = true
sketching.workspace = true
toml.workspace = true
tokio = { workspace = true, features = ["rt", "macros", "sync", "time", "net", "io-util"] }
tokio = { workspace = true, features = ["rt", "fs", "macros", "sync", "time", "net", "io-util"] }
tokio-util = { workspace = true, features = ["codec"] }
tracing.workspace = true
reqwest = { workspace = true, default-features = false }

View file

@ -1,4 +1,4 @@
use std::collections::BTreeSet;
use std::collections::{BTreeSet, HashSet};
use std::num::NonZeroUsize;
use std::ops::{Add, Sub};
use std::path::Path;
@ -15,6 +15,8 @@ use crate::db::Db;
use crate::unix_config::{HomeAttr, UidAttr};
use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser};
// use crate::unix_passwd::{EtcUser, EtcGroup};
const NXCACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(2048) };
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -43,6 +45,8 @@ pub struct CacheLayer {
home_alias: Option<HomeAttr>,
uid_attr_map: UidAttr,
gid_attr_map: UidAttr,
allow_id_overrides: HashSet<Id>,
nxset: Mutex<HashSet<Id>>,
nxcache: Mutex<LruCache<Id, SystemTime>>,
}
@ -72,6 +76,7 @@ impl CacheLayer {
home_alias: Option<HomeAttr>,
uid_attr_map: UidAttr,
gid_attr_map: UidAttr,
allow_id_overrides: Vec<String>,
) -> Result<Self, ()> {
let db = Db::new(path)?;
@ -83,7 +88,7 @@ impl CacheLayer {
}
if pam_allow_groups.is_empty() {
eprintln!("Will not be able to authenticate users, pam_allow_groups config is not configured.");
eprintln!("Will not be able to authorise user logins, pam_allow_groups config is not configured.");
}
// We assume we are offline at start up, and we mark the next "online check" as
@ -100,6 +105,11 @@ impl CacheLayer {
home_alias,
uid_attr_map,
gid_attr_map,
allow_id_overrides: allow_id_overrides
.into_iter()
.map(|name| Id::Name(name))
.collect(),
nxset: Mutex::new(HashSet::new()),
nxcache: Mutex::new(LruCache::new(NXCACHE_SIZE)),
})
}
@ -154,9 +164,31 @@ impl CacheLayer {
nxcache_txn.put(id.clone(), ex_time);
}
pub async fn check_nxcache(&self, id: &Id) -> bool {
let nxcache_txn = self.nxcache.lock().await;
nxcache_txn.contains(id)
pub async fn check_nxcache(&self, id: &Id) -> Option<SystemTime> {
let mut nxcache_txn = self.nxcache.lock().await;
nxcache_txn.get(id).copied()
}
pub async fn reload_nxset(&self, iter: impl Iterator<Item = (String, u32)>) {
let mut nxset_txn = self.nxset.lock().await;
nxset_txn.clear();
for (name, gid) in iter {
let name = Id::Name(name);
let gid = Id::Gid(gid);
// Skip anything that the admin opted in to
if !(self.allow_id_overrides.contains(&gid) || self.allow_id_overrides.contains(&name))
{
debug!("Adding {:?}:{:?} to resolver exclusion set", name, gid);
nxset_txn.insert(name);
nxset_txn.insert(gid);
}
}
}
pub async fn check_nxset(&self, name: &str, idnumber: u32) -> bool {
let nxset_txn = self.nxset.lock().await;
nxset_txn.contains(&Id::Gid(idnumber)) || nxset_txn.contains(&Id::Name(name.to_string()))
}
async fn get_cached_usertoken(
@ -187,11 +219,10 @@ impl CacheLayer {
}
None => {
// it wasn't in the DB - lets see if it's in the nxcache.
let mut nxcache_txn = self.nxcache.lock().await;
match nxcache_txn.get(account_id) {
match self.check_nxcache(account_id).await {
Some(ex_time) => {
let now = SystemTime::now();
if &now >= ex_time {
if now >= ex_time {
// It's in the LRU, but we are past the expiry so
// lets attempt a refresh.
Ok((true, None))
@ -239,11 +270,10 @@ impl CacheLayer {
}
None => {
// it wasn't in the DB - lets see if it's in the nxcache.
let mut nxcache_txn = self.nxcache.lock().await;
match nxcache_txn.get(grp_id) {
match self.check_nxcache(grp_id).await {
Some(ex_time) => {
let now = SystemTime::now();
if &now >= ex_time {
if now >= ex_time {
// It's in the LRU, but we are past the expiry so
// lets attempt a refresh.
Ok((true, None))
@ -271,7 +301,7 @@ impl CacheLayer {
.map_err(|e| {
error!("time conversion error - ex_time less than epoch? {:?}", e);
})?;
// WIP #392
// Check if requested `shell` exists on the system, else use `default_shell`
let requested_shell_exists: bool = token
.shell
@ -295,11 +325,20 @@ impl CacheLayer {
token.shell = Some(self.default_shell.clone())
}
// Filter out groups that are in the nxset
{
let nxset_txn = self.nxset.lock().await;
token.groups.retain(|g| {
!(nxset_txn.contains(&Id::Gid(g.gidnumber))
|| nxset_txn.contains(&Id::Name(g.name.clone())))
});
}
let dbtxn = self.db.write().await;
// We need to add the groups first
token
.groups
.iter()
// We need to add the groups first
.try_for_each(|g| dbtxn.update_group(g, offset.as_secs()))
.and_then(|_|
// So that when we add the account it can make the relationships.
@ -360,9 +399,15 @@ impl CacheLayer {
.await
{
Ok(mut n_tok) => {
// We have the token!
self.set_cache_usertoken(&mut n_tok).await?;
Ok(Some(n_tok))
if self.check_nxset(&n_tok.name, n_tok.gidnumber).await {
// Refuse to release the token, it's in the denied set.
self.delete_cache_usertoken(&n_tok.uuid).await?;
Ok(None)
} else {
// We have the token!
self.set_cache_usertoken(&mut n_tok).await?;
Ok(Some(n_tok))
}
}
Err(e) => {
match e {
@ -440,9 +485,15 @@ impl CacheLayer {
.await
{
Ok(n_tok) => {
// We have the token!
self.set_cache_grouptoken(&n_tok).await?;
Ok(Some(n_tok))
if self.check_nxset(&n_tok.name, n_tok.gidnumber).await {
// Refuse to release the token, it's in the denied set.
self.delete_cache_grouptoken(&n_tok.uuid).await?;
Ok(None)
} else {
// We have the token!
self.set_cache_grouptoken(&n_tok).await?;
Ok(Some(n_tok))
}
}
Err(e) => {
match e {
@ -763,10 +814,16 @@ impl CacheLayer {
.await
{
Ok(Some(mut n_tok)) => {
debug!("online password check success.");
self.set_cache_usertoken(&mut n_tok).await?;
self.set_cache_userpassword(&n_tok.uuid, cred).await?;
Ok(Some(true))
if self.check_nxset(&n_tok.name, n_tok.gidnumber).await {
// Refuse to release the token, it's in the denied set.
self.delete_cache_usertoken(&n_tok.uuid).await?;
Ok(None)
} else {
debug!("online password check success.");
self.set_cache_usertoken(&mut n_tok).await?;
self.set_cache_userpassword(&n_tok.uuid, cred).await?;
Ok(Some(true))
}
}
Ok(None) => {
error!("incorrect password");

View file

@ -28,12 +28,15 @@ use kanidm_proto::constants::DEFAULT_CLIENT_CONFIG_PATH;
use kanidm_unix_common::cache::CacheLayer;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_passwd::{parse_etc_group, parse_etc_passwd};
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse};
use libc::umask;
use sketching::tracing_forest::traits::*;
use sketching::tracing_forest::util::*;
use sketching::tracing_forest::{self};
use tokio::fs::File;
use tokio::io::AsyncReadExt; // for read_to_end()
use tokio::net::{UnixListener, UnixStream};
use tokio::sync::broadcast;
use tokio::sync::mpsc::{channel, Receiver, Sender};
@ -42,6 +45,8 @@ use tokio::time;
use tokio_util::codec::{Decoder, Encoder, Framed};
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
use notify_debouncer_full::{new_debouncer, notify::RecursiveMode, notify::Watcher};
//=== the codec
type AsyncTaskRequest = (TaskRequest, oneshot::Sender<()>);
@ -365,6 +370,29 @@ async fn handle_client(
Ok(())
}
async fn process_etc_passwd_group(cachelayer: &CacheLayer) -> Result<(), Box<dyn Error>> {
let mut file = File::open("/etc/passwd").await?;
let mut contents = vec![];
file.read_to_end(&mut contents).await?;
let users = parse_etc_passwd(contents.as_slice()).map_err(|()| "Invalid passwd content")?;
let mut file = File::open("/etc/group").await?;
let mut contents = vec![];
file.read_to_end(&mut contents).await?;
let groups = parse_etc_group(contents.as_slice()).map_err(|()| "Invalid group content")?;
let id_iter = users
.iter()
.map(|user| (user.name.clone(), user.uid))
.chain(groups.iter().map(|group| (group.name.clone(), group.gid)));
cachelayer.reload_nxset(id_iter).await;
Ok(())
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> ExitCode {
let cuid = get_current_uid();
@ -544,7 +572,6 @@ async fn main() -> ExitCode {
rm_if_exist(cfg.task_sock_path.as_str());
// Check the db path will be okay.
if !cfg.db_path.is_empty() {
let db_path = PathBuf::from(cfg.db_path.as_str());
@ -633,7 +660,6 @@ async fn main() -> ExitCode {
}
};
let cl_inner = match CacheLayer::new(
cfg.db_path.as_str(), // The sqlite db path
cfg.cache_timeout,
@ -645,6 +671,7 @@ async fn main() -> ExitCode {
cfg.home_alias,
cfg.uid_attr_map,
cfg.gid_attr_map,
cfg.allow_local_account_override.clone(),
)
.await
{
@ -669,6 +696,12 @@ async fn main() -> ExitCode {
// Undo umask changes.
let _ = unsafe { umask(before) };
// Pre-process /etc/passwd and /etc/group for nxset
if let Err(_) = process_etc_passwd_group(&cachelayer).await {
error!("Failed to process system id providers");
return ExitCode::FAILURE
}
// Setup the tasks socket first.
let (task_channel_tx, mut task_channel_rx) = channel(16);
let task_channel_tx = Arc::new(task_channel_tx);
@ -724,6 +757,48 @@ async fn main() -> ExitCode {
// TODO: Setup a task that handles pre-fetching here.
let (inotify_tx, mut inotify_rx) = channel(4);
let _watcher =
match new_debouncer(Duration::from_secs(2), None, move |_event| {
let _ = inotify_tx.try_send(true);
})
.and_then(|mut debouncer| {
debouncer.watcher().watch(Path::new("/etc/passwd"), RecursiveMode::NonRecursive)
.map(|()| debouncer)
})
.and_then(|mut debouncer| debouncer.watcher().watch(Path::new("/etc/group"), RecursiveMode::NonRecursive)
.map(|()| debouncer)
)
{
Ok(watcher) => {
watcher
}
Err(e) => {
error!("Failed to setup inotify {:?}", e);
return ExitCode::FAILURE
}
};
let mut c_broadcast_rx = broadcast_tx.subscribe();
let inotify_cachelayer = cachelayer.clone();
let task_c = tokio::spawn(async move {
loop {
tokio::select! {
_ = c_broadcast_rx.recv() => {
break;
}
_ = inotify_rx.recv() => {
if let Err(_) = process_etc_passwd_group(&inotify_cachelayer).await {
error!("Failed to process system id providers");
}
}
}
}
});
// Set the umask while we open the path for most clients.
let before = unsafe { umask(0) };
let listener = match UnixListener::bind(cfg.sock_path.as_str()) {
@ -812,6 +887,7 @@ async fn main() -> ExitCode {
let _ = task_a.await;
let _ = task_b.await;
let _ = task_c.await;
ExitCode::SUCCESS
})

View file

@ -32,4 +32,6 @@ pub mod selinux_util;
#[cfg(target_family = "unix")]
pub mod unix_config;
#[cfg(target_family = "unix")]
pub mod unix_passwd;
#[cfg(target_family = "unix")]
pub mod unix_proto;

View file

@ -25,7 +25,7 @@ use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
include!("./opt/ssh_authorizedkeys.rs");
#[tokio::main]
#[tokio::main(flavor = "current_thread")]
async fn main() -> ExitCode {
let opt = SshAuthorizedOpt::parse();
if opt.debug {

View file

@ -31,6 +31,8 @@ struct ConfigInt {
uid_attr_map: Option<String>,
gid_attr_map: Option<String>,
selinux: Option<bool>,
#[serde(default)]
allow_local_account_override: Vec<String>,
}
#[derive(Debug, Copy, Clone)]
@ -90,6 +92,7 @@ pub struct KanidmUnixdConfig {
pub uid_attr_map: UidAttr,
pub gid_attr_map: UidAttr,
pub selinux: bool,
pub allow_local_account_override: Vec<String>,
}
impl Default for KanidmUnixdConfig {
@ -122,7 +125,12 @@ impl Display for KanidmUnixdConfig {
writeln!(f, "uid_attr_map: {}", self.uid_attr_map)?;
writeln!(f, "gid_attr_map: {}", self.gid_attr_map)?;
writeln!(f, "selinux: {}", self.selinux)
writeln!(f, "selinux: {}", self.selinux)?;
writeln!(
f,
"allow_local_account_override: {:#?}",
self.allow_local_account_override
)
}
}
@ -148,6 +156,7 @@ impl KanidmUnixdConfig {
uid_attr_map: DEFAULT_UID_ATTR_MAP,
gid_attr_map: DEFAULT_GID_ATTR_MAP,
selinux: DEFAULT_SELINUX,
allow_local_account_override: Vec::default(),
}
}
@ -259,6 +268,7 @@ impl KanidmUnixdConfig {
true => selinux_util::supported(),
_ => false,
},
allow_local_account_override: config.allow_local_account_override,
})
}
}

View file

@ -0,0 +1,110 @@
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize,
};
use std::fmt;
#[derive(Serialize, Deserialize, Debug)]
pub struct EtcUser {
pub name: String,
pub password: String,
pub uid: u32,
pub gid: u32,
pub gecos: String,
pub homedir: String,
pub shell: String,
}
pub fn parse_etc_passwd(bytes: &[u8]) -> Result<Vec<EtcUser>, ()> {
use csv::ReaderBuilder;
let mut rdr = ReaderBuilder::new()
.has_headers(false)
.delimiter(b':')
.from_reader(bytes);
rdr.deserialize()
.map(|result| result.map_err(|_e| ()))
.collect::<Result<Vec<EtcUser>, ()>>()
}
fn members<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
D: Deserializer<'de>,
{
struct InnerCsv;
impl<'de> Visitor<'de> for InnerCsv {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string")
}
fn visit_str<E>(self, value: &str) -> Result<Vec<String>, E>
where
E: de::Error,
{
Ok(value.split(',').map(|s| s.to_string()).collect())
}
}
deserializer.deserialize_str(InnerCsv)
}
#[derive(Serialize, Deserialize, Debug)]
pub struct EtcGroup {
pub name: String,
pub password: String,
pub gid: u32,
#[serde(deserialize_with = "members")]
pub members: Vec<String>,
}
pub fn parse_etc_group(bytes: &[u8]) -> Result<Vec<EtcGroup>, ()> {
use csv::ReaderBuilder;
let mut rdr = ReaderBuilder::new()
.has_headers(false)
.delimiter(b':')
.from_reader(bytes);
rdr.deserialize()
.map(|result| result.map_err(|_e| ()))
.collect::<Result<Vec<EtcGroup>, ()>>()
}
#[cfg(test)]
mod tests {
use super::*;
const EXAMPLE_PASSWD: &str = r#"root:x:0:0:root:/root:/bin/bash
systemd-timesync:x:498:498:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:484:484:User for D-Bus:/run/dbus:/usr/sbin/nologin
tftp:x:483:483:TFTP Account:/srv/tftpboot:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/var/lib/nobody:/bin/bash
"#;
const EXAMPLE_GROUP: &str = r#"root:x:0:
shadow:x:15:
trusted:x:42:
users:x:100:
systemd-journal:x:499:
systemd-timesync:x:498:
kmem:x:497:
lock:x:496:
tty:x:5:
wheel:x:481:admin,testuser
"#;
#[test]
fn test_parse_passwd() {
for record in parse_etc_passwd(EXAMPLE_PASSWD.as_bytes()).unwrap() {
println!("{:?}", record);
}
}
#[test]
fn test_parse_group() {
for record in parse_etc_group(EXAMPLE_GROUP.as_bytes()).unwrap() {
println!("{:?}", record);
}
}
}

View file

@ -110,6 +110,7 @@ async fn setup_test(fix_fn: Fixture) -> (CacheLayer, KanidmClient) {
DEFAULT_HOME_ALIAS,
DEFAULT_UID_ATTR_MAP,
DEFAULT_GID_ATTR_MAP,
vec!["masked_group".to_string()],
)
.await
.expect("Failed to build cache layer.");
@ -171,6 +172,13 @@ async fn test_fixture(rsclient: KanidmClient) {
.idm_group_unix_extend("allowed_group", Some(20002))
.await
.unwrap();
// Setup a group that is masked by nxset, but allowed in overrides
rsclient.idm_group_create("masked_group").await.unwrap();
rsclient
.idm_group_unix_extend("masked_group", Some(20003))
.await
.unwrap();
}
#[tokio::test]
@ -620,70 +628,215 @@ async fn test_cache_nxcache() {
assert!(cachelayer.test_connection().await);
// Is it in the nxcache?
assert!(
!cachelayer
.check_nxcache(&Id::Name("root".to_string()))
.await
);
assert!(!cachelayer.check_nxcache(&Id::Gid(0)).await);
assert!(
!cachelayer
.check_nxcache(&Id::Name("root_group".to_string()))
.await
);
assert!(!cachelayer.check_nxcache(&Id::Gid(1)).await);
assert!(cachelayer
.check_nxcache(&Id::Name("oracle".to_string()))
.await
.is_none());
assert!(cachelayer.check_nxcache(&Id::Gid(2000)).await.is_none());
assert!(cachelayer
.check_nxcache(&Id::Name("oracle_group".to_string()))
.await
.is_none());
assert!(cachelayer.check_nxcache(&Id::Gid(3000)).await.is_none());
// Look for the acc id + nss id
let ut = cachelayer
.get_nssaccount_name("root")
.get_nssaccount_name("oracle")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
let ut = cachelayer
.get_nssaccount_gid(0)
.get_nssaccount_gid(2000)
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
let gt = cachelayer
.get_nssgroup_name("root_group")
.get_nssgroup_name("oracle_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
let gt = cachelayer
.get_nssgroup_gid(1)
.get_nssgroup_gid(3000)
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// Should all now be nxed
assert!(
cachelayer
.check_nxcache(&Id::Name("root".to_string()))
.await
);
assert!(cachelayer.check_nxcache(&Id::Gid(0)).await);
assert!(
cachelayer
.check_nxcache(&Id::Name("root_group".to_string()))
.await
);
assert!(cachelayer.check_nxcache(&Id::Gid(1)).await);
assert!(cachelayer
.check_nxcache(&Id::Name("oracle".to_string()))
.await
.is_some());
assert!(cachelayer.check_nxcache(&Id::Gid(2000)).await.is_some());
assert!(cachelayer
.check_nxcache(&Id::Name("oracle_group".to_string()))
.await
.is_some());
assert!(cachelayer.check_nxcache(&Id::Gid(3000)).await.is_some());
// invalidate cache
assert!(cachelayer.invalidate().await.is_ok());
// Both should NOT be in nxcache now.
assert!(
!cachelayer
.check_nxcache(&Id::Name("root".to_string()))
.await
);
assert!(!cachelayer.check_nxcache(&Id::Gid(0)).await);
assert!(
!cachelayer
.check_nxcache(&Id::Name("root_group".to_string()))
.await
);
assert!(!cachelayer.check_nxcache(&Id::Gid(1)).await);
assert!(cachelayer
.check_nxcache(&Id::Name("oracle".to_string()))
.await
.is_none());
assert!(cachelayer.check_nxcache(&Id::Gid(2000)).await.is_none());
assert!(cachelayer
.check_nxcache(&Id::Name("oracle_group".to_string()))
.await
.is_none());
assert!(cachelayer.check_nxcache(&Id::Gid(3000)).await.is_none());
}
#[tokio::test]
async fn test_cache_nxset_account() {
let (cachelayer, _adminclient) = setup_test(fixture(test_fixture)).await;
// Important! This is what sets up that testaccount1 won't be resolved
// because it's in the "local" user set.
cachelayer
.reload_nxset(vec![("testaccount1".to_string(), 20000)].into_iter())
.await;
// Force offline. Show we have no account
cachelayer.mark_offline().await;
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
// go online
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
// get the account
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
// go offline
cachelayer.mark_offline().await;
// still not present, was not cached.
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
// Finally, check it's not in all accounts.
let us = cachelayer
.get_nssaccounts()
.await
.expect("failed to list all accounts");
assert!(us.is_empty());
}
#[tokio::test]
async fn test_cache_nxset_group() {
let (cachelayer, _adminclient) = setup_test(fixture(test_fixture)).await;
// Important! This is what sets up that testgroup1 won't be resolved
// because it's in the "local" group set.
cachelayer
.reload_nxset(vec![("testgroup1".to_string(), 20001)].into_iter())
.await;
// Force offline. Show we have no groups.
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// go online. Get the group
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// go offline. still works
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// clear cache, go online
assert!(cachelayer.invalidate().await.is_ok());
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
// get an account with the group
// DO NOT get the group yet.
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_some());
// go offline.
cachelayer.mark_offline().await;
// show we have the group despite no direct calls
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// Finally, check we only have the upg in the list
let gs = cachelayer
.get_nssgroups()
.await
.expect("failed to list all groups");
assert!(gs.len() == 1);
assert!(gs[0].name == "testaccount1@idm.example.com");
}
#[tokio::test]
async fn test_cache_nxset_allow_overrides() {
let (cachelayer, _adminclient) = setup_test(fixture(test_fixture)).await;
// Important! masked_group is set as an allowed override group even though
// it's been "inserted" to the nxset. This means it will still resolve!
cachelayer
.reload_nxset(vec![("masked_group".to_string(), 20003)].into_iter())
.await;
// Force offline. Show we have no groups.
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("masked_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// go online. Get the group
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
let gt = cachelayer
.get_nssgroup_name("masked_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_some());
// go offline. still works
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("masked_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_some());
}