mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 04:27:02 +01:00
Rework deps (#1079)
This commit is contained in:
parent
8e0238ab97
commit
821b2c05c4
11
.rustfmt.toml
Normal file
11
.rustfmt.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
reorder_imports = true
|
||||
|
||||
## Requires nightly
|
||||
# imports_granularity = "Module"
|
||||
# group_imports = "StdExternalCrate"
|
||||
# format_code_in_doc_comments = true
|
||||
# format_macro_bodies = true
|
||||
# reorder_impl_items = true
|
||||
|
||||
|
255
Cargo.lock
generated
255
Cargo.lock
generated
|
@ -82,6 +82,21 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc-no-stdlib"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
||||
|
||||
[[package]]
|
||||
name = "alloc-stdlib"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
|
@ -186,6 +201,7 @@ version = "0.3.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"flate2",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
|
@ -578,6 +594,27 @@ version = "2.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "3.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
"brotli-decompressor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli-decompressor"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.17"
|
||||
|
@ -602,6 +639,12 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
@ -753,6 +796,12 @@ dependencies = [
|
|||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "compact_jwt"
|
||||
version = "0.2.8"
|
||||
|
@ -850,9 +899,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.16.0"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
|
||||
checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"time 0.3.14",
|
||||
|
@ -865,7 +914,7 @@ version = "0.16.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd"
|
||||
dependencies = [
|
||||
"cookie 0.16.0",
|
||||
"cookie 0.16.1",
|
||||
"idna 0.2.3",
|
||||
"log",
|
||||
"publicsuffix",
|
||||
|
@ -1991,6 +2040,19 @@ dependencies = [
|
|||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
|
||||
dependencies = [
|
||||
"http",
|
||||
"hyper",
|
||||
"rustls",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
|
@ -2061,6 +2123,20 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.23.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.1"
|
||||
|
@ -2174,7 +2250,7 @@ dependencies = [
|
|||
"rusqlite",
|
||||
"saffron",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"serde_cbor_2",
|
||||
"serde_json",
|
||||
"sketching",
|
||||
"smartstring",
|
||||
|
@ -2664,6 +2740,28 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
|
@ -2724,6 +2822,7 @@ dependencies = [
|
|||
"getrandom 0.2.7",
|
||||
"http",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
|
@ -2773,9 +2872,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.41"
|
||||
version = "0.10.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
|
||||
checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
|
@ -2805,9 +2904,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.75"
|
||||
version = "0.9.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
|
||||
checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
|
@ -2919,6 +3018,24 @@ version = "2.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phonenumber"
|
||||
version = "0.3.1+8.12.9"
|
||||
|
@ -3085,9 +3202,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -3124,6 +3241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f"
|
||||
dependencies = [
|
||||
"checked_int_cast",
|
||||
"image",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3341,7 +3459,7 @@ checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc"
|
|||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes",
|
||||
"cookie 0.16.0",
|
||||
"cookie 0.16.1",
|
||||
"cookie_store",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
|
@ -3350,6 +3468,7 @@ dependencies = [
|
|||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
|
@ -3360,19 +3479,38 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"proc-macro-hack",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "route-recognizer"
|
||||
version = "0.2.0"
|
||||
|
@ -3443,6 +3581,27 @@ dependencies = [
|
|||
"nom 7.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.20.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"sct",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
|
@ -3511,7 +3670,6 @@ version = "1.1.0-alpha.9"
|
|||
dependencies = [
|
||||
"async-std",
|
||||
"async-trait",
|
||||
"base64 0.13.0",
|
||||
"compact_jwt",
|
||||
"futures",
|
||||
"futures-util",
|
||||
|
@ -3541,6 +3699,16 @@ dependencies = [
|
|||
"webauthn-authenticator-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.7.0"
|
||||
|
@ -3800,9 +3968,15 @@ dependencies = [
|
|||
"event-listener",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "sketching"
|
||||
version = "0.1.0"
|
||||
version = "1.1.0-alpha.9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"num_enum",
|
||||
|
@ -3861,6 +4035,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "sptr"
|
||||
version = "0.3.2"
|
||||
|
@ -3965,9 +4145,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.100"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
|
||||
checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4027,18 +4207,18 @@ checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.35"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85"
|
||||
checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.35"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783"
|
||||
checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4086,6 +4266,7 @@ dependencies = [
|
|||
"async-compression",
|
||||
"futures-lite",
|
||||
"http-types",
|
||||
"phf",
|
||||
"regex",
|
||||
"tide",
|
||||
]
|
||||
|
@ -4273,6 +4454,17 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"tokio",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.4"
|
||||
|
@ -4441,6 +4633,12 @@ dependencies = [
|
|||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
|
@ -4774,6 +4972,25 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
|
||||
dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wepoll-ffi"
|
||||
version = "0.1.2"
|
||||
|
|
122
Cargo.toml
122
Cargo.toml
|
@ -17,20 +17,131 @@ members = [
|
|||
"kanidmd/score",
|
||||
"orca",
|
||||
"profiles",
|
||||
"sketching",
|
||||
"sketching"
|
||||
]
|
||||
|
||||
exclude = [
|
||||
"kanidm_unix_int/pam_tester"
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = [
|
||||
"William Brown <william@blackhats.net.au>",
|
||||
"James Hodgkinson <james@terminaloutcomes.com>",
|
||||
]
|
||||
rust-version = "1.64"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
[workspace.dependencies]
|
||||
async-std = { version = "^1.12.0", features = ["tokio1"] }
|
||||
async-trait = "^0.1.57"
|
||||
base32 = "^0.4.0"
|
||||
base64 = "^0.13.0"
|
||||
base64urlsafedata = "0.1.0"
|
||||
bytes = "^1.1.0"
|
||||
clap = { version = "^3.2", features = ["derive"] }
|
||||
clap_complete = "^3.2.5"
|
||||
# Forced by saffron
|
||||
chrono = "^0.4.20"
|
||||
compact_jwt = "^0.2.3"
|
||||
# compact_jwt = { path = "../compact_jwt" }
|
||||
concread = "^0.4.0"
|
||||
# concread = { path = "../concread" }
|
||||
crossbeam = "0.8.1"
|
||||
criterion = "^0.4.0"
|
||||
csv = "1.1.6"
|
||||
dialoguer = "0.10.1"
|
||||
dyn-clone = "^1.0.9"
|
||||
fernet = "^0.2.0"
|
||||
filetime = "^0.2.17"
|
||||
futures = "^0.3.21"
|
||||
futures-util = "^0.3.21"
|
||||
gloo = "^0.8.0"
|
||||
gloo-net = "0.2.4"
|
||||
hashbrown = { version = "0.12.3", features = ["serde", "inline-more", "ahash"] }
|
||||
http-types = "^2.12.0"
|
||||
idlset = "^0.2.4"
|
||||
# idlset = { path = "../idlset" }
|
||||
# ldap3_server = { path = "../ldap3_server" }
|
||||
js-sys = "^0.3.58"
|
||||
# RENAME THIS
|
||||
kanidm = { path = "./kanidmd/idm" }
|
||||
kanidm_client = { path = "./kanidm_client" }
|
||||
kanidm_proto = { path = "./kanidm_proto" }
|
||||
kanidm_unix_int = { path = "./kanidm_unix_int" }
|
||||
last-git-commit = "0.2.0"
|
||||
# REMOVE this
|
||||
lazy_static = "^1.4.0"
|
||||
ldap3_proto = "^0.2.3"
|
||||
libc = "^0.2.127"
|
||||
libnss = "^0.4.0"
|
||||
libsqlite3-sys = "^0.25.0"
|
||||
lru = "^0.8.0"
|
||||
mathru = "^0.13.0"
|
||||
num_enum = "^0.5.7"
|
||||
oauth2_ext = { version = "^4.1.0", package = "oauth2" }
|
||||
openssl = "^0.10.41"
|
||||
paste = "^1.0.9"
|
||||
pkg-config = "^0.3.25"
|
||||
profiles = { path = "./profiles" }
|
||||
qrcode = "^0.12.0"
|
||||
r2d2 = "^0.8.9"
|
||||
r2d2_sqlite = "^0.21.0"
|
||||
rand = "^0.8.5"
|
||||
# try to remove this
|
||||
rayon = "^1.5.3"
|
||||
regex = "1.5.6"
|
||||
reqwest = "0.11.11"
|
||||
rpassword = "^7.0.0"
|
||||
rusqlite = "^0.28.0"
|
||||
saffron = "^0.1.0"
|
||||
# Rename this!
|
||||
score = { path = "./kanidmd/score" }
|
||||
serde = "^1.0.142"
|
||||
serde_cbor = { version = "0.12.0-dev", package = "serde_cbor_2" }
|
||||
serde_json = "^1.0.83"
|
||||
serde-wasm-bindgen = "0.4"
|
||||
shellexpand = "^2.1.2"
|
||||
sketching = { path = "./sketching" }
|
||||
smartstring = "^1.0.1"
|
||||
smolset = "^1.3.1"
|
||||
sshkeys = "^0.3.1"
|
||||
|
||||
tide = "^0.16.0"
|
||||
tide-compress = "0.10.6"
|
||||
tide-openssl = "^0.1.1"
|
||||
|
||||
# Unable to increase version due to removing ability to detect
|
||||
# local platform time.
|
||||
time = "=0.2.27"
|
||||
|
||||
tikv-jemallocator = "0.5"
|
||||
|
||||
tokio = "^1.21.1"
|
||||
tokio-openssl = "^0.6.3"
|
||||
tokio-util = "^0.7.4"
|
||||
|
||||
toml = "^0.5.9"
|
||||
touch = "^0.0.1"
|
||||
tracing = { version = "^0.1.35", features = ["max_level_trace", "release_max_level_debug"] }
|
||||
tracing-subscriber = { version = "^0.3.14", features = ["env-filter"] }
|
||||
|
||||
# tracing-forest = { path = "/Users/william/development/tracing-forest/tracing-forest" }
|
||||
tracing-forest = { git = "https://github.com/QnnOkabayashi/tracing-forest.git", rev = "48d78f7294ceee47a22eee5c80964143c4fb3fe1" }
|
||||
|
||||
url = "^2.3.1"
|
||||
urlencoding = "2.1.2"
|
||||
users = "^0.11.0"
|
||||
uuid = "^1.1.2"
|
||||
|
||||
validator = "^0.16.0"
|
||||
|
||||
wasm-bindgen = "^0.2.81"
|
||||
wasm-bindgen-futures = "^0.4.30"
|
||||
wasm-bindgen-test = "0.3.33"
|
||||
|
||||
webauthn-authenticator-rs = "0.4.7"
|
||||
webauthn-rs = "0.4.7"
|
||||
|
@ -40,6 +151,13 @@ webauthn-rs-proto = "0.4.7"
|
|||
# webauthn-rs = { path = "../webauthn-rs/webauthn-rs" }
|
||||
# webauthn-rs-core = { path = "../webauthn-rs/webauthn-rs-core" }
|
||||
# webauthn-rs-proto = { path = "../webauthn-rs/webauthn-rs-proto" }
|
||||
web-sys = "^0.3.60"
|
||||
whoami = "^1.2.3"
|
||||
|
||||
yew = "^0.19.3"
|
||||
yew-agent = "^0.1.0"
|
||||
yew-router = "^0.16.0"
|
||||
zxcvbn = "^2.2.1"
|
||||
|
||||
# enshrinken the WASMs
|
||||
[profile.release.package.kanidmd_web_ui]
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
[package]
|
||||
name = "kanidm_client"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.64"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
description = "Kanidm Client Library"
|
||||
documentation = "https://docs.rs/kanidm_client/latest/kanidm_client/"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
tracing = "^0.1.35"
|
||||
reqwest = { version = "^0.11.11", features=["cookies", "json", "native-tls"] }
|
||||
kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" }
|
||||
serde = { version = "^1.0.142", features = ["derive"] }
|
||||
serde_json = "^1.0.83"
|
||||
time = { version = "=0.2.27", features = ["serde", "std"] }
|
||||
tokio = { version = "^1.21.1", features = ["rt", "net", "time", "macros", "sync", "signal"] }
|
||||
toml = "^0.5.9"
|
||||
uuid = { version = "^1.1.2", features = ["serde", "v4"] }
|
||||
url = { version = "^2.3.1", features = ["serde"] }
|
||||
tracing.workspace = true
|
||||
reqwest = { workspace = true, features=["cookies", "json", "native-tls"] }
|
||||
kanidm_proto.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
time = { workspace = true, features = ["serde", "std"] }
|
||||
tokio = { workspace = true, features = ["rt", "net", "time", "macros", "sync", "signal"] }
|
||||
toml.workspace = true
|
||||
uuid = { workspace = true, features = ["serde", "v4"] }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
webauthn-rs-proto = { workspace = true, features = ["wasm"] }
|
||||
|
||||
|
|
|
@ -13,32 +13,26 @@
|
|||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde_json::error::Error as SerdeJsonError;
|
||||
use std::collections::{BTreeMap, BTreeSet as Set};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::File;
|
||||
#[cfg(target_family = "unix")] // not needed for windows builds
|
||||
use std::fs::{metadata, Metadata};
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Read;
|
||||
|
||||
use std::io::{ErrorKind, Read};
|
||||
#[cfg(target_family = "unix")] // not needed for windows builds
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet as Set;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::*;
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
pub use reqwest::StatusCode;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::error::Error as SerdeJsonError;
|
||||
use tokio::sync::RwLock;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub use reqwest::StatusCode;
|
||||
|
||||
use kanidm_proto::v1::*;
|
||||
use webauthn_rs_proto::{
|
||||
PublicKeyCredential, RegisterPublicKeyCredential, RequestChallengeResponse,
|
||||
};
|
||||
|
@ -1767,6 +1761,7 @@ impl KanidmClient {
|
|||
self.perform_patch_request(format!("/v1/oauth2/{}", id).as_str(), update_oauth2_rs)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn idm_oauth2_rs_prefer_spn_username(&self, id: &str) -> Result<(), ClientError> {
|
||||
let mut update_oauth2_rs = Entry {
|
||||
attrs: BTreeMap::new(),
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use crate::ClientError;
|
||||
use crate::KanidmClient;
|
||||
use kanidm_proto::v1::AccountUnixExtend;
|
||||
use kanidm_proto::v1::CredentialStatus;
|
||||
use kanidm_proto::v1::Entry;
|
||||
use kanidm_proto::v1::SingleStringRequest;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use kanidm_proto::v1::{AccountUnixExtend, CredentialStatus, Entry, SingleStringRequest};
|
||||
|
||||
use crate::{ClientError, KanidmClient};
|
||||
|
||||
impl KanidmClient {
|
||||
pub async fn idm_person_account_list(&self) -> Result<Vec<Entry>, ClientError> {
|
||||
self.perform_get_request("/v1/person").await
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use crate::ClientError;
|
||||
use crate::KanidmClient;
|
||||
use kanidm_proto::v1::AccountUnixExtend;
|
||||
use kanidm_proto::v1::CredentialStatus;
|
||||
use kanidm_proto::v1::Entry;
|
||||
use kanidm_proto::v1::{ApiToken, ApiTokenGenerate};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use kanidm_proto::v1::{AccountUnixExtend, ApiToken, ApiTokenGenerate, CredentialStatus, Entry};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{ClientError, KanidmClient};
|
||||
|
||||
impl KanidmClient {
|
||||
pub async fn idm_service_account_list(&self) -> Result<Vec<Entry>, ClientError> {
|
||||
self.perform_get_request("/v1/service_account").await
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
[package]
|
||||
name = "kanidm_proto"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.64"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
description = "Kanidm Protocol Bindings for serde"
|
||||
documentation = "https://docs.rs/kanidm_proto/latest/kanidm_proto/"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[features]
|
||||
wasm = ["webauthn-rs-proto/wasm"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
base32 = "^0.4.0"
|
||||
base64urlsafedata = "0.1.0"
|
||||
serde = { version = "^1.0.142", features = ["derive"] }
|
||||
serde_json = "^1.0.83"
|
||||
# Can not upgrade due to breaking timezone apis.
|
||||
time = { version = "=0.2.27", features = ["serde", "std"] }
|
||||
url = { version = "^2.3.1", features = ["serde"] }
|
||||
urlencoding = "2.1.2"
|
||||
uuid = { version = "^1.1.2", features = ["serde"] }
|
||||
base32.workspace = true
|
||||
base64urlsafedata.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
time = { workspace = true, features = ["serde", "std"] }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
urlencoding.workspace = true
|
||||
uuid = { workspace = true, features = ["serde"] }
|
||||
webauthn-rs-proto.workspace = true
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
last-git-commit = "0.2.0"
|
||||
last-git-commit.workspace = true
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// User-facing output things
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// This is used in user-facing CLIs to set the formatting for output,
|
||||
/// and defaults to text.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -21,6 +22,7 @@ impl Default for ConsoleOutputMode {
|
|||
|
||||
impl FromStr for ConsoleOutputMode {
|
||||
type Err = &'static str;
|
||||
|
||||
/// This can be safely unwrap'd because it'll always return a default of text
|
||||
/// ```
|
||||
/// use kanidm_proto::messages::ConsoleOutputMode;
|
||||
|
@ -141,7 +143,6 @@ impl Default for AccountChangeMessage {
|
|||
/// msg.output_mode = ConsoleOutputMode::JSON;
|
||||
/// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\",\"src_user\":\"Kani\",\"dest_user\":\"Krabby\"}";
|
||||
/// assert_eq!(format!("{}", msg), expected_result);
|
||||
///
|
||||
/// ```
|
||||
impl fmt::Display for AccountChangeMessage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -149,7 +150,7 @@ impl fmt::Display for AccountChangeMessage {
|
|||
ConsoleOutputMode::JSON => write!(
|
||||
f,
|
||||
"{}",
|
||||
serde_json::to_string(self).unwrap_or(format!("{:?}", self)) // if it fails to JSON serialize, just debug-dump it
|
||||
serde_json::to_string(self).unwrap_or(format!("{:?}", self)) /* if it fails to JSON serialize, just debug-dump it */
|
||||
),
|
||||
ConsoleOutputMode::Text => write!(
|
||||
f,
|
||||
|
@ -182,8 +183,8 @@ impl Default for BasicMessage {
|
|||
|
||||
/// This outputs in either JSON or Text depending on the output_mode setting
|
||||
/// ```
|
||||
/// use std::fmt::format;
|
||||
/// use kanidm_proto::messages::*;
|
||||
/// use std::fmt::format;
|
||||
/// let mut msg = BasicMessage::default();
|
||||
/// msg.action = String::from("cake_eating");
|
||||
/// msg.result = String::from("It was amazing");
|
||||
|
@ -193,9 +194,9 @@ impl Default for BasicMessage {
|
|||
/// assert_eq!(format!("{}", msg), expected_result);
|
||||
///
|
||||
/// msg.output_mode = ConsoleOutputMode::JSON;
|
||||
/// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\"}";
|
||||
/// let expected_result =
|
||||
/// "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\"}";
|
||||
/// assert_eq!(format!("{}", msg), expected_result);
|
||||
///
|
||||
/// ```
|
||||
impl fmt::Display for BasicMessage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -203,7 +204,7 @@ impl fmt::Display for BasicMessage {
|
|||
ConsoleOutputMode::JSON => write!(
|
||||
f,
|
||||
"{}",
|
||||
serde_json::to_string(self).unwrap_or(format!("{:?}", self)) // if it fails to JSON serialize, just debug-dump it
|
||||
serde_json::to_string(self).unwrap_or(format!("{:?}", self)) /* if it fails to JSON serialize, just debug-dump it */
|
||||
),
|
||||
ConsoleOutputMode::Text => {
|
||||
write!(f, "{} - {}: {}", self.status, self.action, self.result,)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs_proto::{
|
||||
CreationChallengeResponse, PublicKeyCredential, RegisterPublicKeyCredential,
|
||||
|
@ -1068,8 +1068,7 @@ impl SingleStringRequest {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::v1::Filter as ProtoFilter;
|
||||
use crate::v1::{TotpAlgo, TotpSecret};
|
||||
use crate::v1::{Filter as ProtoFilter, TotpAlgo, TotpSecret};
|
||||
|
||||
#[test]
|
||||
fn test_protofilter_simple() {
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
[package]
|
||||
name = "kanidm_tools"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.64"
|
||||
edition = "2021"
|
||||
default-run = "kanidm"
|
||||
license = "MPL-2.0"
|
||||
description = "Kanidm Client Tools"
|
||||
documentation = "https://docs.rs/kanidm_tools/latest/kanidm_tools/"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "kanidm_cli"
|
||||
|
@ -29,28 +30,28 @@ name = "kanidm_badlist_preprocess"
|
|||
path = "src/badlist_preprocess.rs"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "^3.2", features = ["derive", "env"] }
|
||||
compact_jwt = "^0.2.3"
|
||||
dialoguer = "^0.10.1"
|
||||
libc = "^0.2.127"
|
||||
kanidm_client = { path = "../kanidm_client", version = "1.1.0-alpha.8" }
|
||||
kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" }
|
||||
qrcode = { version = "^0.12.0", default-features = false }
|
||||
rayon = "^1.5.3"
|
||||
rpassword = "^7.0.0"
|
||||
serde = { version = "^1.0.142", features = ["derive"] }
|
||||
serde_json = "^1.0.83"
|
||||
shellexpand = "^2.1.2"
|
||||
time = { version = "=0.2.27", features = ["serde", "std"] }
|
||||
tracing = "^0.1.35"
|
||||
tracing-subscriber = { version = "^0.3.14", features = ["env-filter", "fmt"] }
|
||||
tokio = { version = "^1.21.1", features = ["rt", "macros"] }
|
||||
url = { version = "^2.3.1", features = ["serde"] }
|
||||
uuid = "^1.1.2"
|
||||
clap = { workspace = true, features = ["derive", "env"] }
|
||||
compact_jwt.workspace = true
|
||||
dialoguer.workspace = true
|
||||
libc.workspace = true
|
||||
kanidm_client.workspace = true
|
||||
kanidm_proto.workspace = true
|
||||
qrcode = { workspace = true, default-features = false }
|
||||
rayon.workspace = true
|
||||
rpassword.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
shellexpand.workspace = true
|
||||
time = { workspace = true, features = ["serde", "std"] }
|
||||
tracing.workspace = true
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
|
||||
tokio = { workspace = true, features = ["rt", "macros"] }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
uuid.workspace = true
|
||||
webauthn-authenticator-rs = { workspace = true, features = ["u2fhid"] }
|
||||
zxcvbn = "^2.2.1"
|
||||
zxcvbn.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "^3.2", features = ["derive"] }
|
||||
clap_complete = { version = "^3.2.5"}
|
||||
uuid = "^1.1.2"
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete.workspace = true
|
||||
uuid.workspace = true
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use uuid::Uuid;
|
||||
|
||||
use clap::{CommandFactory, Parser};
|
||||
use clap_complete::{generate_to, Shell};
|
||||
use uuid::Uuid;
|
||||
|
||||
include!("src/opt/ssh_authorizedkeys.rs");
|
||||
include!("src/opt/badlist_preprocess.rs");
|
||||
|
|
|
@ -14,9 +14,8 @@ use std::io::BufWriter;
|
|||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use kanidm_proto::v1::Modify;
|
||||
|
||||
use clap::Parser;
|
||||
use kanidm_proto::v1::Modify;
|
||||
use rayon::prelude::*;
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use crate::session::read_tokens;
|
||||
use crate::CommonOpt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use dialoguer::{theme::ColorfulTheme, Select};
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
use dialoguer::Select;
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME};
|
||||
use kanidm_proto::v1::UserAuthToken;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::session::read_tokens;
|
||||
use crate::CommonOpt;
|
||||
|
||||
impl CommonOpt {
|
||||
pub fn to_unauth_client(&self) -> KanidmClient {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
extern crate tracing;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
include!("../opt/kanidm.rs");
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
|
||||
use clap::Parser;
|
||||
use kanidm_cli::KanidmClientParser;
|
||||
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::{fmt, EnvFilter};
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
use crate::password_prompt;
|
||||
use crate::{
|
||||
AccountCredential, AccountRadius, AccountSsh, AccountValidity, PersonOpt, PersonPosix,
|
||||
};
|
||||
use dialoguer::{theme::ColorfulTheme, Select};
|
||||
use dialoguer::{Confirm, Input, Password};
|
||||
use std::fmt::{self, Debug};
|
||||
use std::str::FromStr;
|
||||
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
use dialoguer::{Confirm, Input, Password, Select};
|
||||
use kanidm_client::ClientError::Http as ClientErrorHttp;
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus};
|
||||
use kanidm_proto::v1::OperationError::PasswordQuality;
|
||||
use kanidm_proto::v1::{CUIntentToken, CURegState, CUSessionToken, CUStatus, TotpSecret};
|
||||
use qrcode::{render::unicode, QrCode};
|
||||
use std::fmt::{self, Debug};
|
||||
use std::str::FromStr;
|
||||
use qrcode::render::unicode;
|
||||
use qrcode::QrCode;
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
use webauthn_authenticator_rs::u2fhid::U2FHid;
|
||||
use webauthn_authenticator_rs::WebauthnAuthenticator;
|
||||
|
||||
use webauthn_authenticator_rs::{u2fhid::U2FHid, WebauthnAuthenticator};
|
||||
use crate::{
|
||||
password_prompt, AccountCredential, AccountRadius, AccountSsh, AccountValidity, PersonOpt,
|
||||
PersonPosix,
|
||||
};
|
||||
|
||||
impl PersonOpt {
|
||||
pub fn debug(&self) -> bool {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::RawOpt;
|
||||
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::Path;
|
||||
|
||||
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::RawOpt;
|
||||
|
||||
fn read_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> {
|
||||
let f = File::open(path)?;
|
||||
let r = BufReader::new(f);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::{
|
||||
AccountSsh, AccountValidity, ServiceAccountApiToken, ServiceAccountCredential,
|
||||
ServiceAccountOpt, ServiceAccountPosix,
|
||||
};
|
||||
use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
impl ServiceAccountOpt {
|
||||
pub fn debug(&self) -> bool {
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
use crate::common::prompt_for_username_get_username;
|
||||
use crate::{LoginOpt, LogoutOpt, SessionOpt};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::{create_dir, File};
|
||||
use std::io::{self, BufReader, BufWriter, ErrorKind, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::JwsUnverified;
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
use dialoguer::Select;
|
||||
use kanidm_client::{ClientError, KanidmClient};
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthResponse, AuthState, UserAuthToken};
|
||||
#[cfg(target_family = "unix")]
|
||||
use libc::umask;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::{create_dir, File};
|
||||
use std::io::ErrorKind;
|
||||
use std::io::{self, BufReader, BufWriter, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use webauthn_authenticator_rs::{
|
||||
prelude::RequestChallengeResponse, u2fhid::U2FHid, WebauthnAuthenticator,
|
||||
};
|
||||
use webauthn_authenticator_rs::prelude::RequestChallengeResponse;
|
||||
use webauthn_authenticator_rs::u2fhid::U2FHid;
|
||||
use webauthn_authenticator_rs::WebauthnAuthenticator;
|
||||
|
||||
use dialoguer::{theme::ColorfulTheme, Select};
|
||||
|
||||
use compact_jwt::JwsUnverified;
|
||||
use crate::common::prompt_for_username_get_username;
|
||||
use crate::{LoginOpt, LogoutOpt, SessionOpt};
|
||||
|
||||
static TOKEN_DIR: &str = "~/.cache";
|
||||
static TOKEN_PATH: &str = "~/.cache/kanidm_tokens";
|
||||
|
|
|
@ -12,7 +12,6 @@ use std::path::PathBuf;
|
|||
|
||||
use clap::Parser;
|
||||
use kanidm_client::{ClientError, KanidmClientBuilder};
|
||||
|
||||
use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME};
|
||||
use tracing::{debug, error};
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
[package]
|
||||
name = "kanidm_unix_int"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.64"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
description = "Kanidm Unix Integration Clients"
|
||||
documentation = "https://docs.rs/kanidm/latest/kanidm/"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "kanidm_unix_common"
|
||||
|
@ -43,46 +44,42 @@ name = "kanidm_test_auth"
|
|||
path = "src/test_auth.rs"
|
||||
|
||||
[dependencies]
|
||||
kanidm_client = { path = "../kanidm_client" }
|
||||
kanidm_proto = { path = "../kanidm_proto" }
|
||||
kanidm = { path = "../kanidmd/idm" }
|
||||
bytes.workspace = true
|
||||
clap = { workspace = true, features = ["derive", "env"] }
|
||||
futures.workspace = true
|
||||
libc.workspace = true
|
||||
libsqlite3-sys.workspace = true
|
||||
lru.workspace = true
|
||||
kanidm_client.workspace = true
|
||||
kanidm_proto.workspace = true
|
||||
# This is just used for password hashing and tests, so we could
|
||||
# clean this up
|
||||
kanidm.workspace = true
|
||||
|
||||
tracing = "^0.1.35"
|
||||
sketching = { path = "../sketching" }
|
||||
r2d2.workspace = true
|
||||
r2d2_sqlite.workspace = true
|
||||
rpassword.workspace = true
|
||||
rusqlite.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
sketching.workspace = true
|
||||
|
||||
toml = "^0.5.9"
|
||||
rpassword = "^7.0.0"
|
||||
tokio = { version = "^1.21.1", features = ["rt", "macros", "sync", "time", "net", "io-util"] }
|
||||
tokio-util = { version = "^0.7.4", features = ["codec"] }
|
||||
|
||||
futures = "^0.3.21"
|
||||
bytes = "^1.1.0"
|
||||
|
||||
libc = "^0.2.127"
|
||||
serde = { version = "^1.0.142", features = ["derive"] }
|
||||
serde_json = "^1.0.83"
|
||||
clap = { version = "^3.2", features = ["derive", "env"] }
|
||||
|
||||
libsqlite3-sys = "0.25.0"
|
||||
rusqlite = "^0.28.0"
|
||||
r2d2 = "^0.8.10"
|
||||
r2d2_sqlite = "^0.21.0"
|
||||
|
||||
reqwest = "^0.11.11"
|
||||
|
||||
users = "^0.11.0"
|
||||
|
||||
lru = "^0.8.0"
|
||||
toml.workspace = true
|
||||
tokio = { workspace = true, features = ["rt", "macros", "sync", "time", "net", "io-util"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tracing.workspace = true
|
||||
reqwest.workspace = true
|
||||
users.workspace = true
|
||||
|
||||
[features]
|
||||
# default = [ "libsqlite3-sys/bundled" ]
|
||||
|
||||
[dev-dependencies]
|
||||
# kanidm = { path = "../kanidmd/idm" }
|
||||
score = { path = "../kanidmd/score" }
|
||||
score.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "^3.2", features = ["derive"] }
|
||||
clap_complete = "^3.2.5"
|
||||
profiles = { path = "../profiles" }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete.workspace = true
|
||||
profiles.workspace = true
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#![allow(dead_code)]
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{IntoApp, Parser};
|
||||
use clap_complete::{generate_to, Shell};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
include!("src/opt/ssh_authorizedkeys.rs");
|
||||
include!("src/opt/cache_invalidate.rs");
|
||||
include!("src/opt/cache_clear.rs");
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
[package]
|
||||
name = "nss_kanidm"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.59"
|
||||
edition = "2021"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "nss_kanidm"
|
||||
|
@ -11,9 +15,9 @@ crate-type = [ "cdylib" ]
|
|||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
kanidm_unix_int = { path = "../" }
|
||||
libnss = "^0.4.0"
|
||||
libc = "^0.2.127"
|
||||
paste = "^1.0.9"
|
||||
lazy_static = "^1.4.0"
|
||||
kanidm_unix_int.workspace = true
|
||||
libnss.workspace = true
|
||||
libc.workspace = true
|
||||
paste.workspace = true
|
||||
lazy_static.workspace = true
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ use kanidm_unix_common::client_sync::call_daemon_blocking;
|
|||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, NssGroup, NssUser};
|
||||
|
||||
use libnss::group::{Group, GroupHooks};
|
||||
use libnss::interop::Response;
|
||||
use libnss::passwd::{Passwd, PasswdHooks};
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
[package]
|
||||
name = "pam_kanidm"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.59"
|
||||
edition = "2021"
|
||||
links = "pam"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "pam_kanidm"
|
||||
crate-type = [ "cdylib" ]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
kanidm_unix_int = { path = "../" }
|
||||
libc = "^0.2.127"
|
||||
kanidm_unix_int.workspace = true
|
||||
libc.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
pkg-config = "^0.3.25"
|
||||
pkg-config.workspace = true
|
||||
|
|
|
@ -14,19 +14,20 @@
|
|||
// extern crate libc;
|
||||
|
||||
mod pam;
|
||||
use crate::pam::constants::*;
|
||||
use crate::pam::conv::PamConv;
|
||||
use crate::pam::module::{PamHandle, PamHooks};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CStr;
|
||||
|
||||
// use std::os::raw::c_char;
|
||||
use kanidm_unix_common::client_sync::call_daemon_blocking;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
|
||||
|
||||
use crate::pam::constants::*;
|
||||
use crate::pam::conv::PamConv;
|
||||
use crate::pam::module::{PamHandle, PamHooks};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Options {
|
||||
debug: bool,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use libc::{c_char, c_int};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ptr;
|
||||
|
||||
use crate::pam::constants::PamResultCode;
|
||||
use crate::pam::constants::*;
|
||||
use libc::{c_char, c_int};
|
||||
|
||||
use crate::pam::constants::{PamResultCode, *};
|
||||
use crate::pam::module::{PamItem, PamResult};
|
||||
|
||||
#[allow(missing_copy_implementations)]
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
/// Here is full example of a PAM module that would authenticate and authorize everybody:
|
||||
///
|
||||
/// ```
|
||||
/// #[macro_use] extern crate pam;
|
||||
/// #[macro_use]
|
||||
/// extern crate pam;
|
||||
///
|
||||
/// use pam::module::{PamHooks, PamHandle};
|
||||
/// use pam::constants::{PamResultCode, PamFlag};
|
||||
/// use pam::constants::{PamFlag, PamResultCode};
|
||||
/// use pam::module::{PamHandle, PamHooks};
|
||||
/// use std::ffi::CStr;
|
||||
///
|
||||
/// # fn main() {}
|
||||
|
@ -36,6 +37,7 @@ macro_rules! pam_hooks {
|
|||
mod pam_hooks_scope {
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
use $crate::pam::constants::{PamFlag, PamResultCode};
|
||||
use $crate::pam::module::{PamHandle, PamHooks};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
//! Functions for use in pam modules.
|
||||
|
||||
use libc::c_char;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::{mem, ptr};
|
||||
|
||||
use libc::c_char;
|
||||
|
||||
use crate::pam::constants::{PamFlag, PamItemType, PamResultCode, PAM_AUTHTOK};
|
||||
|
||||
/// Opaque type, used as a pointer when making pam API calls.
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
[package]
|
||||
name = "pam_tester"
|
||||
version = "0.1.2"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.59"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pam = "^0.7.0"
|
||||
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
use crate::db::Db;
|
||||
use crate::unix_config::{HomeAttr, UidAttr};
|
||||
use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser};
|
||||
use kanidm_client::ClientError;
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken};
|
||||
use lru::LruCache;
|
||||
use reqwest::StatusCode;
|
||||
use std::collections::BTreeSet;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::ops::{Add, Sub};
|
||||
use std::path::Path;
|
||||
use std::string::ToString;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use kanidm_client::{ClientError, KanidmClient};
|
||||
use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken};
|
||||
use lru::LruCache;
|
||||
use reqwest::StatusCode;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
|
||||
use crate::db::Db;
|
||||
use crate::unix_config::{HomeAttr, UidAttr};
|
||||
use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser};
|
||||
|
||||
const NXCACHE_SIZE: usize = 2048;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
extern crate tracing;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use futures::executor::block_on;
|
||||
|
||||
use kanidm_unix_common::client::call_daemon;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
extern crate tracing;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use futures::executor::block_on;
|
||||
|
||||
use kanidm_unix_common::client::call_daemon;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use bytes::{BufMut, BytesMut};
|
||||
use futures::SinkExt;
|
||||
use futures::StreamExt;
|
||||
use std::error::Error;
|
||||
use std::io::Error as IoError;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use tokio::net::UnixStream;
|
||||
// use tokio::runtime::Builder;
|
||||
use tokio_util::codec::Framed;
|
||||
|
@ -14,8 +13,8 @@ use crate::unix_proto::{ClientRequest, ClientResponse};
|
|||
struct ClientCodec;
|
||||
|
||||
impl Decoder for ClientCodec {
|
||||
type Item = ClientResponse;
|
||||
type Error = IoError;
|
||||
type Item = ClientResponse;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
match serde_json::from_slice::<ClientResponse>(&src) {
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use std::error::Error;
|
||||
use std::io::Error as IoError;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::{Error as IoError, ErrorKind, Read, Write};
|
||||
use std::os::unix::net::UnixStream;
|
||||
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use crate::unix_proto::{ClientRequest, ClientResponse};
|
||||
|
|
|
@ -10,10 +10,18 @@
|
|||
#![deny(clippy::needless_pass_by_value)]
|
||||
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use std::error::Error;
|
||||
use std::fs::metadata;
|
||||
use std::io;
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use clap::{Arg, ArgAction, Command};
|
||||
use futures::SinkExt;
|
||||
use futures::StreamExt;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use kanidm::utils::file_permissions_readonly;
|
||||
use kanidm_client::KanidmClientBuilder;
|
||||
use kanidm_proto::constants::DEFAULT_CLIENT_CONFIG_PATH;
|
||||
|
@ -22,22 +30,14 @@ use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
|||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse};
|
||||
use libc::umask;
|
||||
use sketching::tracing_forest::{self, traits::*, util::*};
|
||||
use std::error::Error;
|
||||
use std::fs::metadata;
|
||||
use std::io;
|
||||
use std::io::Error as IoError;
|
||||
use std::io::ErrorKind;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use sketching::tracing_forest::traits::*;
|
||||
use sketching::tracing_forest::util::*;
|
||||
use sketching::tracing_forest::{self};
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::time;
|
||||
use tokio_util::codec::Framed;
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
|
||||
|
||||
//=== the codec
|
||||
|
@ -47,8 +47,8 @@ type AsyncTaskRequest = (TaskRequest, oneshot::Sender<()>);
|
|||
struct ClientCodec;
|
||||
|
||||
impl Decoder for ClientCodec {
|
||||
type Item = ClientRequest;
|
||||
type Error = io::Error;
|
||||
type Item = ClientRequest;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
match serde_json::from_slice::<ClientRequest>(&src) {
|
||||
|
@ -85,8 +85,8 @@ impl ClientCodec {
|
|||
struct TaskCodec;
|
||||
|
||||
impl Decoder for TaskCodec {
|
||||
type Item = TaskResponse;
|
||||
type Error = io::Error;
|
||||
type Item = TaskResponse;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
match serde_json::from_slice::<TaskResponse>(&src) {
|
||||
|
|
|
@ -13,12 +13,10 @@
|
|||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
// use futures::executor::block_on;
|
||||
|
||||
use kanidm_unix_common::client_sync::call_daemon_blocking;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
use libc::umask;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::cache::Id;
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
|
||||
use kanidm::be::dbvalue::DbPasswordV1;
|
||||
use kanidm::credential::policy::CryptoPolicy;
|
||||
use kanidm::credential::Password;
|
||||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
use libc::umask;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
|
||||
use crate::cache::Id;
|
||||
|
||||
pub struct Db {
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
|
@ -732,9 +732,10 @@ impl<'a> Drop for DbTxn<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
|
||||
use super::Db;
|
||||
use crate::cache::Id;
|
||||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
|
||||
const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test";
|
||||
const TESTACCOUNT1_PASSWORD_B: &str = "password b for account1 test";
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use futures::executor::block_on;
|
||||
|
||||
use kanidm_unix_common::client::call_daemon;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
|
|
|
@ -10,35 +10,31 @@
|
|||
#![deny(clippy::needless_pass_by_value)]
|
||||
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use users::{get_effective_gid, get_effective_uid};
|
||||
|
||||
use std::os::unix::fs::symlink;
|
||||
|
||||
use libc::{lchown, umask};
|
||||
use std::ffi::CString;
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use futures::SinkExt;
|
||||
use futures::StreamExt;
|
||||
use sketching::tracing_forest::{self, traits::*, util::*};
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::os::unix::fs::symlink;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use tokio::net::UnixStream;
|
||||
use tokio::time;
|
||||
use tokio_util::codec::Framed;
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
use std::{fs, io};
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
use kanidm_unix_common::unix_proto::{HomeDirectoryInfo, TaskRequest, TaskResponse};
|
||||
use libc::{lchown, umask};
|
||||
use sketching::tracing_forest::traits::*;
|
||||
use sketching::tracing_forest::util::*;
|
||||
use sketching::tracing_forest::{self};
|
||||
use tokio::net::UnixStream;
|
||||
use tokio::time;
|
||||
use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||
use users::{get_effective_gid, get_effective_uid};
|
||||
|
||||
struct TaskCodec;
|
||||
|
||||
impl Decoder for TaskCodec {
|
||||
type Item = TaskRequest;
|
||||
type Error = io::Error;
|
||||
type Item = TaskRequest;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
match serde_json::from_slice::<TaskRequest>(&src) {
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
extern crate tracing;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use futures::executor::block_on;
|
||||
|
||||
use kanidm_unix_common::client::call_daemon;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
use crate::constants::{
|
||||
DEFAULT_CACHE_TIMEOUT, DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_GID_ATTR_MAP,
|
||||
DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL, DEFAULT_SOCK_PATH,
|
||||
DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read};
|
||||
use std::path::Path;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::constants::{
|
||||
DEFAULT_CACHE_TIMEOUT, DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_GID_ATTR_MAP,
|
||||
DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL, DEFAULT_SOCK_PATH,
|
||||
DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ConfigInt {
|
||||
db_path: Option<String>,
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
#![deny(warnings)]
|
||||
use std::future::Future;
|
||||
use std::net::TcpStream;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm::audit::LogLevel;
|
||||
use kanidm::config::{Configuration, IntegrationTestConfig, ServerRole};
|
||||
use score::create_server_core;
|
||||
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
use kanidm_unix_common::cache::{CacheLayer, Id};
|
||||
use kanidm_unix_common::constants::{
|
||||
DEFAULT_GID_ATTR_MAP, DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX,
|
||||
DEFAULT_SHELL, DEFAULT_UID_ATTR_MAP,
|
||||
};
|
||||
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
use score::create_server_core;
|
||||
use tokio::task;
|
||||
|
||||
static PORT_ALLOC: AtomicU16 = AtomicU16::new(28080);
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
[package]
|
||||
name = "daemon"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.59"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
description = "Kanidm Server Daemon"
|
||||
documentation = "https://docs.rs/kanidm/latest/kanidm/"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -17,25 +18,25 @@ name = "kanidmd"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
kanidm = { path = "../idm" }
|
||||
kanidm_proto = { path = "../../kanidm_proto" }
|
||||
score = { path = "../score" }
|
||||
sketching = { path = "../../sketching" }
|
||||
kanidm.workspace = true
|
||||
kanidm_proto.workspace = true
|
||||
score.workspace = true
|
||||
sketching.workspace = true
|
||||
|
||||
clap = { version = "^3.2", features = ["derive", "env"] }
|
||||
serde = { version = "^1.0.142", features = ["derive"] }
|
||||
tokio = { version = "^1.21.1", features = ["rt-multi-thread", "macros", "signal"] }
|
||||
toml = "0.5.9"
|
||||
clap = { workspace = true, features = ["env"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal"] }
|
||||
toml.workspace = true
|
||||
|
||||
[target.'cfg(target_family = "windows")'.dependencies]
|
||||
whoami = "^1.2.3"
|
||||
whoami.workspace = true
|
||||
|
||||
[target.'cfg(not(target_family = "windows"))'.dependencies]
|
||||
users = "^0.11.0"
|
||||
tikv-jemallocator = "0.5"
|
||||
users.workspace = true
|
||||
tikv-jemallocator.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
clap = { version = "^3.2", features = ["derive"] }
|
||||
clap_complete = "^3.2.5"
|
||||
profiles = { path = "../../profiles" }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete.workspace = true
|
||||
profiles.workspace = true
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::path::PathBuf;
|
|||
|
||||
use clap::{Args, IntoApp, Parser, Subcommand};
|
||||
use clap_complete::{generate_to, Shell};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
include!("../idm/src/audit_loglevel.rs");
|
||||
|
|
|
@ -14,25 +14,15 @@
|
|||
#[global_allocator]
|
||||
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
||||
|
||||
#[cfg(not(target_family = "windows"))] // not needed for windows builds
|
||||
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
|
||||
#[cfg(target_family = "windows")] // for windows builds
|
||||
use whoami;
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::fs::{metadata, File, Metadata};
|
||||
|
||||
use std::io::Read;
|
||||
#[cfg(target_family = "unix")]
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
|
||||
use sketching::tracing_forest::{self, traits::*, util::*};
|
||||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use kanidm::audit::LogLevel;
|
||||
use kanidm::config::{Configuration, OnlineBackup, ServerRole};
|
||||
#[cfg(not(target_family = "windows"))]
|
||||
|
@ -43,8 +33,14 @@ use score::{
|
|||
domain_rename_core, recover_account_core, reindex_server_core, restore_server_core,
|
||||
vacuum_server_core, verify_server_core,
|
||||
};
|
||||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use serde::Deserialize;
|
||||
use sketching::tracing_forest::traits::*;
|
||||
use sketching::tracing_forest::util::*;
|
||||
use sketching::tracing_forest::{self};
|
||||
#[cfg(not(target_family = "windows"))] // not needed for windows builds
|
||||
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
|
||||
#[cfg(target_family = "windows")] // for windows builds
|
||||
use whoami;
|
||||
|
||||
include!("./opt.rs");
|
||||
|
||||
|
|
|
@ -1,98 +1,91 @@
|
|||
[package]
|
||||
name = "kanidm"
|
||||
version = "1.1.0-alpha.9"
|
||||
authors = ["William Brown <william@blackhats.net.au>"]
|
||||
rust-version = "1.59"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
description = "Kanidm Server Library and Binary"
|
||||
documentation = "https://docs.rs/kanidm/latest/kanidm/"
|
||||
homepage = "https://github.com/kanidm/kanidm/"
|
||||
repository = "https://github.com/kanidm/kanidm/"
|
||||
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "kanidm"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "scaling_10k"
|
||||
harness = false
|
||||
|
||||
[dependencies]
|
||||
async-std = { version = "^1.12.0", features = ["tokio1"] }
|
||||
async-trait = "^0.1.57"
|
||||
base64 = "^0.13.0"
|
||||
base64urlsafedata = "0.1.0"
|
||||
chrono = "^0.4.20"
|
||||
compact_jwt = "^0.2.3"
|
||||
concread = "^0.4.0"
|
||||
dyn-clone = "^1.0.9"
|
||||
fernet = { version = "^0.2.0", features = ["fernet_danger_timestamps"] }
|
||||
filetime = "^0.2.17"
|
||||
futures = "^0.3.21"
|
||||
futures-util = "^0.3.21"
|
||||
hashbrown = { version = "0.12.3", features = ["serde", "inline-more", "ahash"] }
|
||||
idlset = { version = "^0.2.4" }
|
||||
kanidm_proto = { path = "../../kanidm_proto" }
|
||||
lazy_static = "^1.4.0"
|
||||
ldap3_proto = "^0.2.3"
|
||||
libc = "^0.2.127"
|
||||
libsqlite3-sys = "^0.25.0"
|
||||
num_enum = "^0.5.7"
|
||||
openssl = "^0.10.41"
|
||||
r2d2 = "^0.8.9"
|
||||
r2d2_sqlite = "^0.21.0"
|
||||
rand = "^0.8.5"
|
||||
regex = "^1.5.6"
|
||||
saffron = "^0.1.0"
|
||||
serde = { version = "^1.0.142", features = ["derive"] }
|
||||
serde_cbor = "^0.11.2"
|
||||
serde_json = "^1.0.83"
|
||||
smartstring = { version = "^1.0.1", features = ["serde"] }
|
||||
smolset = "^1.3.1"
|
||||
sshkeys = "^0.3.1"
|
||||
tide = "^0.16.0"
|
||||
time = { version = "=0.2.27", features = ["serde", "std"] }
|
||||
tokio = { version = "^1.21.1", features = ["net", "sync", "time"] }
|
||||
tokio-util = { version = "^0.7.4", features = ["codec"] }
|
||||
toml = "^0.5.9"
|
||||
touch = "^0.0.1"
|
||||
async-std.workspace = true
|
||||
async-trait.workspace = true
|
||||
base64.workspace = true
|
||||
base64urlsafedata.workspace = true
|
||||
chrono.workspace = true
|
||||
compact_jwt.workspace = true
|
||||
concread.workspace = true
|
||||
dyn-clone.workspace = true
|
||||
fernet = { workspace = true, features = ["fernet_danger_timestamps"] }
|
||||
filetime.workspace = true
|
||||
futures.workspace = true
|
||||
futures-util.workspace = true
|
||||
hashbrown.workspace = true
|
||||
idlset.workspace = true
|
||||
kanidm_proto.workspace = true
|
||||
lazy_static.workspace = true
|
||||
ldap3_proto.workspace = true
|
||||
libc.workspace = true
|
||||
libsqlite3-sys.workspace = true
|
||||
num_enum.workspace = true
|
||||
openssl.workspace = true
|
||||
r2d2.workspace = true
|
||||
r2d2_sqlite.workspace = true
|
||||
rand.workspace = true
|
||||
regex.workspace = true
|
||||
saffron.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_cbor.workspace = true
|
||||
serde_json.workspace = true
|
||||
sketching.workspace = true
|
||||
smartstring = { workspace = true, features = ["serde"] }
|
||||
smolset.workspace = true
|
||||
sshkeys.workspace = true
|
||||
tide.workspace = true
|
||||
time = { workspace = true, features = ["serde", "std"] }
|
||||
tokio = { workspace = true, features = ["net", "sync", "time"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
toml.workspace = true
|
||||
touch.workspace = true
|
||||
|
||||
sketching = { path = "../../sketching" }
|
||||
tracing = { version = "^0.1.35", features = ["attributes"] }
|
||||
tracing = { workspace = true, features = ["attributes"] }
|
||||
|
||||
url = { version = "^2.3.1", features = ["serde"] }
|
||||
urlencoding = "2.1.2"
|
||||
uuid = { version = "^1.1.2", features = ["serde", "v4" ] }
|
||||
validator = { version = "^0.16.0", features = ["phone"] }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
urlencoding.workspace = true
|
||||
uuid = { workspace = true, features = ["serde", "v4" ] }
|
||||
validator = { workspace = true, features = ["phone"] }
|
||||
webauthn-rs = { workspace = true, features = ["resident-key-support", "preview-features", "danger-credential-internals"] }
|
||||
webauthn-rs-core.workspace = true
|
||||
zxcvbn = "^2.2.1"
|
||||
zxcvbn.workspace = true
|
||||
|
||||
# because windows really can't build without the bundled one
|
||||
[target.'cfg(target_family = "windows")'.dependencies.rusqlite]
|
||||
version = "^0.28.0"
|
||||
features = ["bundled"]
|
||||
|
||||
[target.'cfg(not(target_family = "windows"))'.dependencies.rusqlite]
|
||||
version = "^0.28.0"
|
||||
|
||||
[target.'cfg(target_family = "windows")'.dependencies]
|
||||
whoami = "^1.2.3"
|
||||
|
||||
rusqlite = { workspace = true, features = ["bundled"] }
|
||||
whoami.workspace = true
|
||||
|
||||
[target.'cfg(not(target_family = "windows"))'.dependencies]
|
||||
users = "^0.11.0"
|
||||
|
||||
rusqlite.workspace = true
|
||||
users.workspace = true
|
||||
|
||||
[features]
|
||||
# default = [ "libsqlite3-sys/bundled", "openssl/vendored" ]
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "^0.4.0", features = ["html_reports"] }
|
||||
# For testing webauthn
|
||||
criterion = { workspace = true, features = ["html_reports"] }
|
||||
webauthn-authenticator-rs.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
profiles = { path = "../../profiles" }
|
||||
|
||||
[[bench]]
|
||||
name = "scaling_10k"
|
||||
harness = false
|
||||
profiles.workspace = true
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use async_std::task;
|
||||
use criterion::{
|
||||
criterion_group, criterion_main, BenchmarkId, Criterion, SamplingMode, Throughput,
|
||||
};
|
||||
|
||||
use kanidm;
|
||||
use kanidm::entry::{Entry, EntryInit, EntryNew};
|
||||
use kanidm::entry_init;
|
||||
|
@ -11,9 +13,6 @@ use kanidm::server::QueryServer;
|
|||
use kanidm::utils::duration_from_epoch_now;
|
||||
use kanidm::value::Value;
|
||||
|
||||
use async_std::task;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub fn scaling_user_create_single(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("user_create_single");
|
||||
group.sample_size(10);
|
||||
|
|
|
@ -12,31 +12,28 @@
|
|||
//! search.
|
||||
//! - the ability to turn an entry into a partial-entry for results send
|
||||
//! requirements (also search).
|
||||
//!
|
||||
|
||||
// use concread::collections::bptree::*;
|
||||
use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn};
|
||||
use concread::cowcell::*;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use std::collections::BTreeSet;
|
||||
// use hashbrown::HashSet;
|
||||
use std::cell::Cell;
|
||||
use std::collections::BTreeSet;
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
|
||||
use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn};
|
||||
use concread::cowcell::*;
|
||||
use kanidm_proto::v1::{Filter as ProtoFilter, OperationError};
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced, EntrySealed};
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent};
|
||||
use crate::filter::{Filter, FilterValid, FilterValidResolved};
|
||||
use crate::identity::{IdentType, IdentityId};
|
||||
use crate::modify::Modify;
|
||||
use crate::prelude::*;
|
||||
use crate::value::PartialValue;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent};
|
||||
use crate::identity::{IdentType, IdentityId};
|
||||
|
||||
use tracing::trace;
|
||||
|
||||
// const ACP_RELATED_SEARCH_CACHE_MAX: usize = 2048;
|
||||
// const ACP_RELATED_SEARCH_CACHE_LOCAL: usize = 16;
|
||||
|
||||
|
@ -408,6 +405,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
&self,
|
||||
) -> &mut ARCacheReadTxn<'a, (IdentityId, Filter<FilterValid>), Filter<FilterValidResolved>, ()>;
|
||||
|
||||
#[instrument(level = "debug", name = "access::search_related_acp", skip_all)]
|
||||
fn search_related_acp<'b>(
|
||||
&'b self,
|
||||
rec_entry: &Entry<EntrySealed, EntryCommitted>,
|
||||
|
@ -443,9 +441,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
} else {
|
||||
*/
|
||||
// else, we calculate this, and then stash/cache the uuids.
|
||||
let related_acp: Vec<(&AccessControlSearch, Filter<FilterValidResolved>)> =
|
||||
spanned!("access::search_related_acp<uncached>", {
|
||||
search_state
|
||||
let related_acp: Vec<(&AccessControlSearch, Filter<FilterValidResolved>)> = search_state
|
||||
.iter()
|
||||
.filter_map(|acs| {
|
||||
// Now resolve the receiver filter
|
||||
|
@ -463,11 +459,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
// A possible solution is to change the filter resolve function
|
||||
// such that it takes an entry, rather than an event, but that
|
||||
// would create issues in search.
|
||||
match (&acs.acp.receiver).resolve(
|
||||
ident,
|
||||
None,
|
||||
Some(acp_resolve_filter_cache),
|
||||
) {
|
||||
match (&acs.acp.receiver).resolve(ident, None, Some(acp_resolve_filter_cache)) {
|
||||
Ok(f_res) => {
|
||||
if rec_entry.entry_match_no_index(&f_res) {
|
||||
// Now, for each of the acp's that apply to our receiver, resolve their
|
||||
|
@ -488,16 +480,12 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
}
|
||||
Err(e) => {
|
||||
admin_error!(
|
||||
?e,
|
||||
"A internal filter/event was passed for resolution!?!?"
|
||||
);
|
||||
admin_error!(?e, "A internal filter/event was passed for resolution!?!?");
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
.collect();
|
||||
|
||||
/*
|
||||
// Stash the uuids into the cache.
|
||||
|
@ -511,6 +499,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
|
||||
// Contains all the way to eval acps to entries
|
||||
#[instrument(level = "debug", name = "access::search_filter_entries", skip_all)]
|
||||
fn search_filter_entries(
|
||||
&self,
|
||||
se: &SearchEvent,
|
||||
|
@ -525,7 +514,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
IdentType::User(u) => &u.entry,
|
||||
};
|
||||
spanned!("access::search_filter_entries", {
|
||||
trace!(event = %se.ident, "Access check for search (filter) event");
|
||||
|
||||
// First get the set of acps that apply to this receiver
|
||||
|
@ -543,9 +531,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
let requested_attrs: BTreeSet<&str> = se.filter_orig.get_attr_set();
|
||||
|
||||
// For each entry
|
||||
let allowed_entries: Vec<Arc<EntrySealedCommitted>> = spanned!(
|
||||
"access::search_filter_entries<allowed_entries>",
|
||||
{
|
||||
let allowed_entries: Vec<Arc<EntrySealedCommitted>> =
|
||||
entries
|
||||
.into_iter()
|
||||
.filter(|e| {
|
||||
|
@ -580,9 +566,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
security_access!(?decision, "search attr decision");
|
||||
decision
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
);
|
||||
.collect();
|
||||
|
||||
if allowed_entries.is_empty() {
|
||||
security_access!("denied ❌");
|
||||
|
@ -591,9 +575,13 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
|
||||
Ok(allowed_entries)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "debug",
|
||||
name = "access::search_filter_entry_attributes",
|
||||
skip_all
|
||||
)]
|
||||
fn search_filter_entry_attributes(
|
||||
&self,
|
||||
se: &SearchEvent,
|
||||
|
@ -620,7 +608,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
IdentType::User(u) => &u.entry,
|
||||
};
|
||||
|
||||
spanned!("access::search_filter_entry_attributes", {
|
||||
/*
|
||||
* Super similar to above (could even re-use some parts). Given a set of entries,
|
||||
* reduce the attribute sets on them to "what is visible". This is ONLY called on
|
||||
|
@ -634,8 +621,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
// Get the relevant acps for this receiver.
|
||||
let related_acp: Vec<(&AccessControlSearch, _)> =
|
||||
self.search_related_acp(rec_entry, &se.ident);
|
||||
let related_acp: Vec<(&AccessControlSearch, _)> =
|
||||
if let Some(r_attrs) = se.attrs.as_ref() {
|
||||
let related_acp: Vec<(&AccessControlSearch, _)> = if let Some(r_attrs) = se.attrs.as_ref() {
|
||||
related_acp
|
||||
.into_iter()
|
||||
.filter(|(acs, _)| !acs.attrs.is_disjoint(r_attrs))
|
||||
|
@ -658,9 +644,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
.map(|vs| vs.iter().map(|s| s.as_str()).collect());
|
||||
|
||||
// For each entry
|
||||
let allowed_entries: Vec<Entry<EntryReduced, EntryCommitted>> =
|
||||
spanned!("access::search_filter_entry_attributes<allowed_entries>", {
|
||||
entries
|
||||
let allowed_entries: Vec<Entry<EntryReduced, EntryCommitted>> = entries
|
||||
.into_iter()
|
||||
.map(|e| {
|
||||
// Get the set of attributes you can see for this entry
|
||||
|
@ -701,13 +685,9 @@ pub trait AccessControlsTransaction<'a> {
|
|||
);
|
||||
|
||||
// Now purge the attrs that are NOT allowed.
|
||||
spanned!(
|
||||
"access::search_filter_entry_attributes<reduce_attributes>",
|
||||
{ e.reduce_attributes(&allowed_attrs) }
|
||||
)
|
||||
e.reduce_attributes(&allowed_attrs)
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
.collect();
|
||||
|
||||
if allowed_entries.is_empty() {
|
||||
security_access!("reduced to empty set on all entries ❌");
|
||||
|
@ -719,9 +699,9 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
|
||||
Ok(allowed_entries)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "access::modify_related_acp", skip_all)]
|
||||
fn modify_related_acp<'b>(
|
||||
&'b self,
|
||||
rec_entry: &Entry<EntrySealed, EntryCommitted>,
|
||||
|
@ -733,9 +713,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
|
||||
// Find the acps that relate to the caller, and compile their related
|
||||
// target filters.
|
||||
let related_acp: Vec<(&AccessControlModify, _)> = spanned!(
|
||||
"access::modify_related_acp<uncached>",
|
||||
{
|
||||
let related_acp: Vec<(&AccessControlModify, _)> =
|
||||
modify_state
|
||||
.iter()
|
||||
.filter_map(|acs| {
|
||||
|
@ -766,14 +744,13 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
);
|
||||
.collect();
|
||||
|
||||
related_acp
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
#[instrument(level = "debug", name = "access::modify_allow_operation", skip_all)]
|
||||
fn modify_allow_operation(
|
||||
&self,
|
||||
me: &ModifyEvent,
|
||||
|
@ -787,7 +764,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
IdentType::User(u) => &u.entry,
|
||||
};
|
||||
spanned!("access::modify_allow_operation", {
|
||||
trace!("Access check for modify event: {}", me.ident);
|
||||
|
||||
// Pre-check if the no-no purge class is present
|
||||
|
@ -932,10 +908,10 @@ pub trait AccessControlsTransaction<'a> {
|
|||
security_access!("denied ❌");
|
||||
}
|
||||
Ok(r)
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
#[instrument(level = "debug", name = "access::create_allow_operation", skip_all)]
|
||||
fn create_allow_operation(
|
||||
&self,
|
||||
ce: &CreateEvent,
|
||||
|
@ -949,7 +925,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
IdentType::User(u) => &u.entry,
|
||||
};
|
||||
spanned!("access::create_allow_operation", {
|
||||
trace!("Access check for create event: {}", ce.ident);
|
||||
|
||||
// Some useful references we'll use for the remainder of the operation
|
||||
|
@ -1065,9 +1040,9 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
|
||||
Ok(r)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "access::delete_allow_operation", skip_all)]
|
||||
fn delete_allow_operation(
|
||||
&self,
|
||||
de: &DeleteEvent,
|
||||
|
@ -1081,7 +1056,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
IdentType::User(u) => &u.entry,
|
||||
};
|
||||
spanned!("access::delete_allow_operation", {
|
||||
trace!("Access check for delete event: {}", de.ident);
|
||||
|
||||
// Some useful references we'll use for the remainder of the operation
|
||||
|
@ -1158,9 +1132,9 @@ pub trait AccessControlsTransaction<'a> {
|
|||
security_access!("denied ❌");
|
||||
}
|
||||
Ok(r)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "access::effective_permission_check", skip_all)]
|
||||
fn effective_permission_check(
|
||||
&self,
|
||||
ident: &Identity,
|
||||
|
@ -1186,7 +1160,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
IdentType::User(u) => &u.entry,
|
||||
};
|
||||
|
||||
spanned!("access::effective_permission_check", {
|
||||
trace!(ident = %ident, "Effective permission check");
|
||||
// I think we seperate this to multiple checks ...?
|
||||
|
||||
|
@ -1295,7 +1268,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
});
|
||||
|
||||
Ok(effective_permissions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1522,15 +1494,17 @@ impl AccessControls {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::uuid;
|
||||
|
||||
use crate::access::{
|
||||
AccessControlCreate, AccessControlDelete, AccessControlModify, AccessControlProfile,
|
||||
AccessControlSearch, AccessControls, AccessControlsTransaction, AccessEffectivePermission,
|
||||
};
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent};
|
||||
use crate::prelude::*;
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
use uuid::uuid;
|
||||
|
||||
macro_rules! acp_from_entry_err {
|
||||
(
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
use tracing::{error, info, instrument, trace};
|
||||
|
||||
use chrono::{DateTime, SecondsFormat, Utc};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, AuthRequest, BackupCodesView, CURequest, CUSessionToken, CUStatus, CredentialStatus,
|
||||
Entry as ProtoEntry, OperationError, RadiusAuthToken, SearchRequest, SearchResponse,
|
||||
UnixGroupToken, UnixUserToken, WhoamiResponse,
|
||||
};
|
||||
use ldap3_proto::simple::*;
|
||||
use regex::Regex;
|
||||
use tracing::{error, info, instrument, trace};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::be::BackendTransaction;
|
||||
|
||||
use crate::event::{
|
||||
AuthEvent, AuthResult, OnlineBackupEvent, SearchEvent, SearchResult, WhoamiResult,
|
||||
};
|
||||
use crate::filter::{Filter, FilterInvalid};
|
||||
use crate::idm::credupdatesession::CredentialUpdateSessionToken;
|
||||
use crate::idm::event::{
|
||||
CredentialStatusEvent, RadiusAuthTokenEvent, ReadBackupCodeEvent, UnixGroupTokenEvent,
|
||||
UnixUserAuthEvent, UnixUserTokenEvent,
|
||||
};
|
||||
use kanidm_proto::v1::{BackupCodesView, OperationError, RadiusAuthToken};
|
||||
|
||||
use crate::filter::{Filter, FilterInvalid};
|
||||
use crate::idm::oauth2::{
|
||||
AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest,
|
||||
AccessTokenResponse, AuthorisationRequest, AuthorisePermitSuccess, AuthoriseResponse,
|
||||
|
@ -26,20 +31,7 @@ use crate::idm::oauth2::{
|
|||
use crate::idm::server::{IdmServer, IdmServerTransaction};
|
||||
use crate::idm::serviceaccount::ListApiTokenEvent;
|
||||
use crate::ldap::{LdapBoundToken, LdapResponseState, LdapServer};
|
||||
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, AuthRequest, CURequest, CUSessionToken, CUStatus, CredentialStatus, SearchRequest,
|
||||
SearchResponse, UnixGroupToken, UnixUserToken, WhoamiResponse,
|
||||
};
|
||||
|
||||
use regex::Regex;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use uuid::Uuid;
|
||||
|
||||
use ldap3_proto::simple::*;
|
||||
use std::convert::TryFrom;
|
||||
use crate::prelude::*;
|
||||
|
||||
// ===========================================================
|
||||
|
||||
|
@ -94,14 +86,6 @@ impl QueryServerReadV1 {
|
|||
// Begin a read
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
// ! NOTICE: The inner function contains a short-circuiting `return`, which is only exits the closure.
|
||||
// ! If we removed the `lperf_op_segment` and kept the inside, this would short circuit before logging `audit`.
|
||||
// ! However, since we immediately return `res` after logging `audit`, and we should be removing the lperf stuff
|
||||
// ! and the logging of `audit` at the same time, it is ok if the inner code short circuits the whole function because
|
||||
// ! there is no work to be done afterwards.
|
||||
// ! However, if we want to do work after `res` is calculated, we need to pass `spanned` a closure instead of a block
|
||||
// ! in order to not short-circuit the entire function.
|
||||
let res = spanned!("actors::v1_read::handle<SearchMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -121,8 +105,6 @@ impl QueryServerReadV1 {
|
|||
let entries = idms_prox_read.qs_read.search_ext(&search)?;
|
||||
|
||||
SearchResult::new(&idms_prox_read.qs_read, &entries).map(SearchResult::response)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
|
@ -184,21 +166,22 @@ impl QueryServerReadV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
trace!(eventid = ?msg.eventid, "Begin online backup event");
|
||||
|
||||
let now: DateTime<Utc> = Utc::now();
|
||||
let timestamp = now.to_rfc3339_opts(SecondsFormat::Secs, true);
|
||||
#[allow(deprecated)]
|
||||
let now = time::OffsetDateTime::now_local();
|
||||
let timestamp = now.format(time::Format::Rfc3339);
|
||||
let dest_file = format!("{}/backup-{}.json", outpath, timestamp);
|
||||
|
||||
match Path::new(&dest_file).exists() {
|
||||
true => {
|
||||
if Path::new(&dest_file).exists() {
|
||||
error!(
|
||||
"Online backup file {} already exists, will not owerwrite it.",
|
||||
"Online backup file {} already exists, will not overwrite it.",
|
||||
dest_file
|
||||
);
|
||||
return Err(OperationError::InvalidState);
|
||||
}
|
||||
false => {
|
||||
|
||||
// Scope to limit the read txn.
|
||||
{
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
spanned!("actors::v1_read::handle<OnlineBackupEvent>", {
|
||||
idms_prox_read
|
||||
.qs_read
|
||||
.get_be_txn()
|
||||
|
@ -210,8 +193,6 @@ impl QueryServerReadV1 {
|
|||
error!("Online backup failed to create {}: {:?}", dest_file, e);
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// pattern to find automatically generated backup files
|
||||
|
@ -314,14 +295,6 @@ impl QueryServerReadV1 {
|
|||
// Begin a read
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
// ! NOTICE: The inner function contains a short-circuiting `return`, which is only exits the closure.
|
||||
// ! If we removed the `lperf_op_segment` and kept the inside, this would short circuit before logging `audit`.
|
||||
// ! However, since we immediately return `res` after logging `audit`, and we should be removing the lperf stuff
|
||||
// ! and the logging of `audit` at the same time, it is ok if the inner code short circuits the whole function because
|
||||
// ! there is no work to be done afterwards.
|
||||
// ! However, if we want to do work after `res` is calculated, we need to pass `spanned` a closure instead of a block
|
||||
// ! in order to not short-circuit the entire function.
|
||||
let res = spanned!("actors::v1_read::handle<WhoamiMessage>", {
|
||||
// Make an event from the whoami request. This will process the event and
|
||||
// generate a selfuuid search.
|
||||
//
|
||||
|
@ -350,17 +323,14 @@ impl QueryServerReadV1 {
|
|||
Some(e) if entries.is_empty() => {
|
||||
WhoamiResult::new(&idms_prox_read.qs_read, &e).map(WhoamiResult::response)
|
||||
}
|
||||
Some(_) => Err(OperationError::InvalidState), // Somehow matched multiple entries...
|
||||
Some(_) => Err(OperationError::InvalidState), /* Somehow matched multiple entries... */
|
||||
_ => Err(OperationError::NoMatchingEntries),
|
||||
}
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "search2",
|
||||
skip(self, uat, filter, attrs, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalsearch(
|
||||
|
@ -372,7 +342,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<Vec<ProtoEntry>, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<InternalSearchMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -400,14 +369,11 @@ impl QueryServerReadV1 {
|
|||
.map(|ok_sr| ok_sr.into_proto_array()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "search_recycled",
|
||||
skip(self, uat, filter, attrs, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalsearchrecycled(
|
||||
|
@ -420,7 +386,6 @@ impl QueryServerReadV1 {
|
|||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
|
||||
let res = spanned!("actors::v1_read::handle<InternalSearchRecycledMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -448,14 +413,11 @@ impl QueryServerReadV1 {
|
|||
.map(|ok_sr| ok_sr.into_proto_array()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "radius_read",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalradiusread(
|
||||
|
@ -466,7 +428,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<Option<String>, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<InternalRadiusReadMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -512,14 +473,11 @@ impl QueryServerReadV1 {
|
|||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "radius_token_read",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalradiustokenread(
|
||||
|
@ -531,7 +489,6 @@ impl QueryServerReadV1 {
|
|||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_read = self.idms.proxy_read_async().await;
|
||||
|
||||
let res = spanned!("actors::v1_read::handle<InternalRadiusTokenReadMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -563,14 +520,11 @@ impl QueryServerReadV1 {
|
|||
trace!(?rate, "Begin event");
|
||||
|
||||
idms_prox_read.get_radiusauthtoken(&rate, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "unix_user_token_read",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalunixusertokenread(
|
||||
|
@ -582,9 +536,6 @@ impl QueryServerReadV1 {
|
|||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_read = self.idms.proxy_read_async().await;
|
||||
|
||||
let res = spanned!(
|
||||
"actors::v1_read::handle<InternalUnixUserTokenReadMessage>",
|
||||
{
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -617,14 +568,10 @@ impl QueryServerReadV1 {
|
|||
|
||||
idms_prox_read.get_unixusertoken(&rate, ct)
|
||||
}
|
||||
);
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "unix_group_token_read",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalunixgrouptokenread(
|
||||
|
@ -635,9 +582,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<UnixGroupToken, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!(
|
||||
"actors::v1_read::handle<InternalUnixGroupTokenReadMessage>",
|
||||
{
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -670,14 +614,10 @@ impl QueryServerReadV1 {
|
|||
|
||||
idms_prox_read.get_unixgrouptoken(&rate)
|
||||
}
|
||||
);
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "ssh_key_read",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalsshkeyread(
|
||||
|
@ -688,7 +628,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<Vec<String>, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<InternalSshKeyReadMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -736,14 +675,11 @@ impl QueryServerReadV1 {
|
|||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "ssh_key_tag_read",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalsshkeytagread(
|
||||
|
@ -755,7 +691,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<Option<String>, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<InternalSshKeyTagReadMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -805,14 +740,11 @@ impl QueryServerReadV1 {
|
|||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "service_account_api_token_get",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_service_account_api_token_get(
|
||||
|
@ -844,8 +776,7 @@ impl QueryServerReadV1 {
|
|||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_account_unix_auth",
|
||||
skip(self, uat, uuid_or_name, cred, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmaccountunixauth(
|
||||
|
@ -857,7 +788,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<Option<UnixUserToken>, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idm_auth = self.idms.auth_async().await;
|
||||
// let res = spanned!("actors::v1_read::handle<IdmAccountUnixAuthMessage>", {
|
||||
// resolve the id
|
||||
let ident = idm_auth
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -891,14 +821,12 @@ impl QueryServerReadV1 {
|
|||
|
||||
security_info!(?res, "Sending result");
|
||||
|
||||
// res });
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_status",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialstatus(
|
||||
|
@ -910,7 +838,6 @@ impl QueryServerReadV1 {
|
|||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_read = self.idms.proxy_read_async().await;
|
||||
|
||||
let res = spanned!("actors::v1_read::handle<IdmCredentialStatusMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -941,14 +868,11 @@ impl QueryServerReadV1 {
|
|||
trace!(?cse, "Begin event");
|
||||
|
||||
idms_prox_read.get_credentialstatus(&cse)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_backup_code_view",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmbackupcodeview(
|
||||
|
@ -960,7 +884,6 @@ impl QueryServerReadV1 {
|
|||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_read = self.idms.proxy_read_async().await;
|
||||
|
||||
let res = spanned!("actors::v1_read::handle<IdmBackupCodeViewMessage>", {
|
||||
let ident = idms_prox_read
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -991,14 +914,11 @@ impl QueryServerReadV1 {
|
|||
trace!(?rbce, "Begin event");
|
||||
|
||||
idms_prox_read.get_backup_codes(&rbce)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_update_status",
|
||||
skip(self, session_token, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialupdatestatus(
|
||||
|
@ -1008,7 +928,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<CUStatus, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_cred_update = self.idms.cred_update_transaction_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<IdmCredentialUpdateStatus>", {
|
||||
let session_token = CredentialUpdateSessionToken {
|
||||
token_enc: session_token.token,
|
||||
};
|
||||
|
@ -1023,14 +942,11 @@ impl QueryServerReadV1 {
|
|||
e
|
||||
})
|
||||
.map(|sta| sta.into())
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_update",
|
||||
skip(self, session_token, scr, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialupdate(
|
||||
|
@ -1041,7 +957,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<CUStatus, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_cred_update = self.idms.cred_update_transaction_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<IdmCredentialUpdate>", {
|
||||
let session_token = CredentialUpdateSessionToken {
|
||||
token_enc: session_token.token,
|
||||
};
|
||||
|
@ -1159,14 +1074,11 @@ impl QueryServerReadV1 {
|
|||
}),
|
||||
}
|
||||
.map(|sta| sta.into())
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_authorise",
|
||||
skip(self, uat, auth_req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_authorise(
|
||||
|
@ -1177,7 +1089,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<AuthoriseResponse, Oauth2Error> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<Oauth2Authorise>", {
|
||||
let (ident, uat) = idms_prox_read
|
||||
.validate_and_parse_uat(uat.as_deref(), ct)
|
||||
.and_then(|uat| {
|
||||
|
@ -1192,14 +1103,11 @@ impl QueryServerReadV1 {
|
|||
|
||||
// Now we can send to the idm server for authorisation checking.
|
||||
idms_prox_read.check_oauth2_authorisation(&ident, &uat, &auth_req, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_authorise_permit",
|
||||
skip(self, uat, consent_req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_authorise_permit(
|
||||
|
@ -1210,7 +1118,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<AuthorisePermitSuccess, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<Oauth2AuthorisePermit>", {
|
||||
let (ident, uat) = idms_prox_read
|
||||
.validate_and_parse_uat(uat.as_deref(), ct)
|
||||
.and_then(|uat| {
|
||||
|
@ -1224,14 +1131,11 @@ impl QueryServerReadV1 {
|
|||
})?;
|
||||
|
||||
idms_prox_read.check_oauth2_authorise_permit(&ident, &uat, &consent_req, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_authorise_reject",
|
||||
skip(self, uat, consent_req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_authorise_reject(
|
||||
|
@ -1242,7 +1146,6 @@ impl QueryServerReadV1 {
|
|||
) -> Result<Url, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<Oauth2AuthoriseReject>", {
|
||||
let (ident, uat) = idms_prox_read
|
||||
.validate_and_parse_uat(uat.as_deref(), ct)
|
||||
.and_then(|uat| {
|
||||
|
@ -1256,14 +1159,11 @@ impl QueryServerReadV1 {
|
|||
})?;
|
||||
|
||||
idms_prox_read.check_oauth2_authorise_reject(&ident, &uat, &consent_req, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_token_exchange",
|
||||
skip(self, client_authz, token_req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_token_exchange(
|
||||
|
@ -1274,17 +1174,13 @@ impl QueryServerReadV1 {
|
|||
) -> Result<AccessTokenResponse, Oauth2Error> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<Oauth2TokenExchange>", {
|
||||
// Now we can send to the idm server for authorisation checking.
|
||||
idms_prox_read.check_oauth2_token_exchange(client_authz.as_deref(), &token_req, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_token_introspect",
|
||||
skip(self, client_authz, intr_req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_token_introspect(
|
||||
|
@ -1295,17 +1191,13 @@ impl QueryServerReadV1 {
|
|||
) -> Result<AccessTokenIntrospectResponse, Oauth2Error> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<Oauth2TokenIntrospect>", {
|
||||
// Now we can send to the idm server for introspection checking.
|
||||
idms_prox_read.check_oauth2_token_introspect(&client_authz, &intr_req, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_openid_userinfo",
|
||||
skip(self, client_id, client_authz, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_openid_userinfo(
|
||||
|
@ -1316,16 +1208,12 @@ impl QueryServerReadV1 {
|
|||
) -> Result<OidcToken, Oauth2Error> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<OidcUserinfo>", {
|
||||
idms_prox_read.oauth2_openid_userinfo(&client_id, &client_authz, ct)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_openid_discovery",
|
||||
skip(self, client_id, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_openid_discovery(
|
||||
|
@ -1334,16 +1222,12 @@ impl QueryServerReadV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<OidcDiscoveryResponse, OperationError> {
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<OidcDiscovery>", {
|
||||
idms_prox_read.oauth2_openid_discovery(&client_id)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_openid_publickey",
|
||||
skip(self, client_id, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_openid_publickey(
|
||||
|
@ -1352,30 +1236,22 @@ impl QueryServerReadV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<JwkKeySet, OperationError> {
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<OidcPublickey>", {
|
||||
idms_prox_read.oauth2_openid_publickey(&client_id)
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "get_domain_display_name",
|
||||
skip(self, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn get_domain_display_name(&self, eventid: Uuid) -> String {
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
let res = spanned!("actors::v1_read::handle<DomainDisplayName>", {
|
||||
idms_prox_read.qs_read.get_domain_display_name().to_string()
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "auth_valid",
|
||||
skip(self, uat, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_auth_valid(
|
||||
|
@ -1386,7 +1262,6 @@ impl QueryServerReadV1 {
|
|||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_read = self.idms.proxy_read_async().await;
|
||||
|
||||
let res = spanned!("actors::v1_read::handle<AuthValid>", {
|
||||
idms_prox_read
|
||||
.validate_and_parse_uat(uat.as_deref(), ct)
|
||||
.map(|_| ())
|
||||
|
@ -1394,14 +1269,11 @@ impl QueryServerReadV1 {
|
|||
admin_error!("Invalid token: {:?}", e);
|
||||
e
|
||||
})
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "ldap_request",
|
||||
skip(self, eventid, protomsg, uat)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_ldaprequest(
|
||||
|
@ -1410,7 +1282,6 @@ impl QueryServerReadV1 {
|
|||
protomsg: LdapMsg,
|
||||
uat: Option<LdapBoundToken>,
|
||||
) -> Option<LdapResponseState> {
|
||||
// let res = spanned!( "actors::v1_read::handle<LdapRequestMessage>", {
|
||||
let res = match ServerOps::try_from(protomsg) {
|
||||
Ok(server_op) => self
|
||||
.ldap
|
||||
|
@ -1428,7 +1299,6 @@ impl QueryServerReadV1 {
|
|||
format!("Invalid Request {:?}", &eventid).as_str(),
|
||||
)),
|
||||
};
|
||||
// });
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,43 +1,35 @@
|
|||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tracing::{info, instrument, span, trace, Level};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::idm::credupdatesession::{
|
||||
CredentialUpdateIntentToken, CredentialUpdateSessionToken, InitCredentialUpdateEvent,
|
||||
InitCredentialUpdateIntentEvent,
|
||||
use kanidm_proto::v1::{
|
||||
AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest,
|
||||
Entry as ProtoEntry, GroupUnixExtend, Modify as ProtoModify, ModifyList as ProtoModifyList,
|
||||
ModifyRequest, OperationError,
|
||||
};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{info, instrument, span, trace, Level};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::event::{
|
||||
CreateEvent, DeleteEvent, ModifyEvent, PurgeRecycledEvent, PurgeTombstoneEvent,
|
||||
ReviveRecycledEvent,
|
||||
};
|
||||
use crate::filter::{Filter, FilterInvalid};
|
||||
use crate::idm::credupdatesession::{
|
||||
CredentialUpdateIntentToken, CredentialUpdateSessionToken, InitCredentialUpdateEvent,
|
||||
InitCredentialUpdateIntentEvent,
|
||||
};
|
||||
use crate::idm::delayed::DelayedAction;
|
||||
use crate::idm::event::{
|
||||
GeneratePasswordEvent, RegenerateRadiusSecretEvent, UnixPasswordChangeEvent,
|
||||
};
|
||||
use crate::modify::{Modify, ModifyInvalid, ModifyList};
|
||||
use crate::value::{PartialValue, Value};
|
||||
use kanidm_proto::v1::OperationError;
|
||||
|
||||
use crate::filter::{Filter, FilterInvalid};
|
||||
use crate::idm::delayed::DelayedAction;
|
||||
use crate::idm::server::{IdmServer, IdmServerTransaction};
|
||||
use crate::idm::serviceaccount::{DestroyApiTokenEvent, GenerateApiTokenEvent};
|
||||
use crate::modify::{Modify, ModifyInvalid, ModifyList};
|
||||
use crate::prelude::*;
|
||||
use crate::utils::duration_from_epoch_now;
|
||||
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use kanidm_proto::v1::Modify as ProtoModify;
|
||||
use kanidm_proto::v1::ModifyList as ProtoModifyList;
|
||||
use kanidm_proto::v1::{
|
||||
AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest,
|
||||
GroupUnixExtend, ModifyRequest,
|
||||
};
|
||||
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use uuid::Uuid;
|
||||
use crate::value::{PartialValue, Value};
|
||||
|
||||
pub struct QueryServerWriteV1 {
|
||||
_log_level: Option<u32>,
|
||||
|
@ -63,6 +55,7 @@ impl QueryServerWriteV1 {
|
|||
&(*x_ptr)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
async fn modify_from_parts(
|
||||
&self,
|
||||
uat: Option<String>,
|
||||
|
@ -71,7 +64,6 @@ impl QueryServerWriteV1 {
|
|||
filter: Filter<FilterInvalid>,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
spanned!("modify_from_parts", {
|
||||
let ct = duration_from_epoch_now();
|
||||
|
||||
let ident = idms_prox_write
|
||||
|
@ -109,9 +101,9 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
async fn modify_from_internal_parts(
|
||||
&self,
|
||||
uat: Option<String>,
|
||||
|
@ -120,7 +112,6 @@ impl QueryServerWriteV1 {
|
|||
filter: Filter<FilterInvalid>,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
spanned!("modify_from_internal_parts", {
|
||||
let ct = duration_from_epoch_now();
|
||||
|
||||
let ident = idms_prox_write
|
||||
|
@ -161,13 +152,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "create",
|
||||
skip(self, uat, req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_create(
|
||||
|
@ -177,7 +166,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
let res = spanned!("actors::v1_write::handle<CreateMessage>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
|
||||
let ident = idms_prox_write
|
||||
|
@ -201,15 +189,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.create(&crt)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
});
|
||||
// At the end of the event we send it for logging.
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "modify",
|
||||
skip(self, uat, req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_modify(
|
||||
|
@ -219,7 +203,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
let res = spanned!("actors::v1_write::handle<ModifyMessage>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -242,14 +225,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "delete",
|
||||
skip(self, uat, req, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_delete(
|
||||
|
@ -259,7 +239,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
let res = spanned!("actors::v1_write::handle<DeleteMessage>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -281,14 +260,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.delete(&del)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "patch",
|
||||
skip(self, uat, filter, update, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internalpatch(
|
||||
|
@ -300,7 +276,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
// Given a protoEntry, turn this into a modification set.
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
let res = spanned!("actors::v1_write::handle<InternalPatch>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -310,18 +285,13 @@ impl QueryServerWriteV1 {
|
|||
})?;
|
||||
|
||||
// Transform the ProtoEntry to a Modlist
|
||||
let modlist =
|
||||
ModifyList::from_patch(&update, &idms_prox_write.qs_write).map_err(|e| {
|
||||
let modlist = ModifyList::from_patch(&update, &idms_prox_write.qs_write).map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid Patch Request");
|
||||
e
|
||||
})?;
|
||||
|
||||
let mdf = ModifyEvent::from_internal_parts(
|
||||
ident,
|
||||
&modlist,
|
||||
&filter,
|
||||
&idms_prox_write.qs_write,
|
||||
)
|
||||
let mdf =
|
||||
ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
e
|
||||
|
@ -333,14 +303,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
});
|
||||
res.map(|_| ())
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "delete2",
|
||||
skip(self, uat, filter, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_internaldelete(
|
||||
|
@ -350,7 +317,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
let res = spanned!("actors::v1_write::handle<InternalDeleteMessage>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -372,14 +338,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.delete(&del)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "revive_recycled",
|
||||
skip(self, uat, filter, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_reviverecycled(
|
||||
|
@ -389,7 +352,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
let res = spanned!("actors::v1_write::handle<ReviveRecycledMessage>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -397,8 +359,7 @@ impl QueryServerWriteV1 {
|
|||
admin_error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let rev =
|
||||
match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) {
|
||||
let rev = match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin revive");
|
||||
|
@ -412,14 +373,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.revive_recycled(&rev)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "service_account_credential_generate",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_service_account_credential_generate(
|
||||
|
@ -430,7 +388,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<String, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<InternalCredentialSetMessage>", {
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -461,14 +418,11 @@ impl QueryServerWriteV1 {
|
|||
idms_prox_write
|
||||
.generate_account_password(&gpe)
|
||||
.and_then(|r| idms_prox_write.commit().map(|_| r))
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "service_account_credential_generate",
|
||||
skip(self, uat, uuid_or_name, label, expiry, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_service_account_api_token_generate(
|
||||
|
@ -510,7 +464,6 @@ impl QueryServerWriteV1 {
|
|||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "service_account_credential_generate",
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
|
@ -551,8 +504,7 @@ impl QueryServerWriteV1 {
|
|||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_update",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialupdate(
|
||||
|
@ -563,7 +515,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(CUSessionToken, CUStatus), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmCredentialUpdate>", {
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -597,14 +548,11 @@ impl QueryServerWriteV1 {
|
|||
sta.into(),
|
||||
)
|
||||
})
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_update_intent",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialupdateintent(
|
||||
|
@ -616,7 +564,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<CUIntentToken, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmCredentialUpdateIntent>", {
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -648,14 +595,11 @@ impl QueryServerWriteV1 {
|
|||
.map(|tok| CUIntentToken {
|
||||
token: tok.intent_id,
|
||||
})
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_exchange_intent",
|
||||
skip(self, intent_token, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialexchangeintent(
|
||||
|
@ -665,7 +609,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(CUSessionToken, CUStatus), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmCredentialExchangeIntent>", {
|
||||
let intent_token = CredentialUpdateIntentToken {
|
||||
intent_id: intent_token.token,
|
||||
};
|
||||
|
@ -688,14 +631,11 @@ impl QueryServerWriteV1 {
|
|||
sta.into(),
|
||||
)
|
||||
})
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_update_commit",
|
||||
skip(self, session_token, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialupdatecommit(
|
||||
|
@ -705,7 +645,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmCredentialUpdateCommit>", {
|
||||
let session_token = CredentialUpdateSessionToken {
|
||||
token_enc: session_token.token,
|
||||
};
|
||||
|
@ -720,14 +659,11 @@ impl QueryServerWriteV1 {
|
|||
);
|
||||
e
|
||||
})
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_credential_update_cancel",
|
||||
skip(self, session_token, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmcredentialupdatecancel(
|
||||
|
@ -737,7 +673,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmCredentialUpdateCancel>", {
|
||||
let session_token = CredentialUpdateSessionToken {
|
||||
token_enc: session_token.token,
|
||||
};
|
||||
|
@ -752,14 +687,11 @@ impl QueryServerWriteV1 {
|
|||
);
|
||||
e
|
||||
})
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "handle_service_account_into_person",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_service_account_into_person(
|
||||
|
@ -770,7 +702,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmServiceAccountIntoPerson>", {
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -788,14 +719,11 @@ impl QueryServerWriteV1 {
|
|||
idms_prox_write
|
||||
.service_account_into_person(&ident, target_uuid)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "regenerate_radius_secret",
|
||||
skip(self, uat, uuid_or_name, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_regenerateradius(
|
||||
|
@ -806,9 +734,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<String, OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!(
|
||||
"actors::v1_write::handle<InternalRegenerateRadiusMessage>",
|
||||
{
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -841,14 +766,10 @@ impl QueryServerWriteV1 {
|
|||
.regenerate_radius_secret(&rrse)
|
||||
.and_then(|r| idms_prox_write.commit().map(|_| r))
|
||||
}
|
||||
);
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "purge_attribute",
|
||||
skip(self, uat, uuid_or_name, attr, filter, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_purgeattribute(
|
||||
|
@ -861,7 +782,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
spanned!("actors::v1_write::handle<PurgeAttributeMessage>", {
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -896,13 +816,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "remove_attribute_values",
|
||||
skip(self, uat, uuid_or_name, attr, values, filter, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_removeattributevalues(
|
||||
|
@ -915,7 +833,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
spanned!("actors::v1_write::handle<RemoveAttributeValuesMessage>", {
|
||||
let ct = duration_from_epoch_now();
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
|
@ -958,7 +875,6 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
|
@ -1121,8 +1037,7 @@ impl QueryServerWriteV1 {
|
|||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "idm_account_unix_set_cred",
|
||||
skip(self, uat, uuid_or_name, cred, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_idmaccountunixsetcred(
|
||||
|
@ -1134,7 +1049,6 @@ impl QueryServerWriteV1 {
|
|||
) -> Result<(), OperationError> {
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
let res = spanned!("actors::v1_write::handle<IdmAccountUnixSetCredMessage>", {
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(uat.as_deref(), ct)
|
||||
.map_err(|e| {
|
||||
|
@ -1166,14 +1080,11 @@ impl QueryServerWriteV1 {
|
|||
.set_unix_account_password(&upce)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
.map(|_| ())
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_scopemap_create",
|
||||
skip(self, uat, filter, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_scopemap_create(
|
||||
|
@ -1187,7 +1098,6 @@ impl QueryServerWriteV1 {
|
|||
// Because this is from internal, we can generate a real modlist, rather
|
||||
// than relying on the proto ones.
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
spanned!("handle_oauth2_scopemap_create", {
|
||||
let ct = duration_from_epoch_now();
|
||||
|
||||
let ident = idms_prox_write
|
||||
|
@ -1208,11 +1118,7 @@ impl QueryServerWriteV1 {
|
|||
let ml = ModifyList::new_append(
|
||||
"oauth2_rs_scope_map",
|
||||
Value::new_oauthscopemap(group_uuid, scopes.into_iter().collect()).ok_or_else(
|
||||
|| {
|
||||
OperationError::InvalidAttribute(
|
||||
"Invalid Oauth Scope Map syntax".to_string(),
|
||||
)
|
||||
},
|
||||
|| OperationError::InvalidAttribute("Invalid Oauth Scope Map syntax".to_string()),
|
||||
)?,
|
||||
);
|
||||
|
||||
|
@ -1235,13 +1141,11 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "oauth2_scopemap_delete",
|
||||
skip(self, uat, filter, eventid)
|
||||
skip_all,
|
||||
fields(uuid = ?eventid)
|
||||
)]
|
||||
pub async fn handle_oauth2_scopemap_delete(
|
||||
|
@ -1252,7 +1156,6 @@ impl QueryServerWriteV1 {
|
|||
eventid: Uuid,
|
||||
) -> Result<(), OperationError> {
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
spanned!("handle_oauth2_scopemap_create", {
|
||||
let ct = duration_from_epoch_now();
|
||||
|
||||
let ident = idms_prox_write
|
||||
|
@ -1291,21 +1194,18 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.modify(&mdf)
|
||||
.and_then(|_| idms_prox_write.commit().map(|_| ()))
|
||||
})
|
||||
}
|
||||
|
||||
// ===== These below are internal only event types. =====
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "purge_tombstone_event",
|
||||
skip(self, msg)
|
||||
skip_all,
|
||||
fields(uuid = ?msg.eventid)
|
||||
)]
|
||||
pub(crate) async fn handle_purgetombstoneevent(&self, msg: PurgeTombstoneEvent) {
|
||||
trace!(?msg, "Begin purge tombstone event");
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
|
||||
spanned!("actors::v1_write::handle<PurgeTombstoneEvent>", {
|
||||
let res = idms_prox_write
|
||||
.qs_write
|
||||
.purge_tombstones()
|
||||
|
@ -1313,19 +1213,16 @@ impl QueryServerWriteV1 {
|
|||
admin_info!(?res, "Purge tombstones result");
|
||||
#[allow(clippy::expect_used)]
|
||||
res.expect("Invalid Server State");
|
||||
});
|
||||
}
|
||||
|
||||
#[instrument(
|
||||
level = "info",
|
||||
name = "purge_recycled_event",
|
||||
skip(self, msg)
|
||||
skip_all,
|
||||
fields(uuid = ?msg.eventid)
|
||||
)]
|
||||
pub(crate) async fn handle_purgerecycledevent(&self, msg: PurgeRecycledEvent) {
|
||||
trace!(?msg, "Begin purge recycled event");
|
||||
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await;
|
||||
spanned!("actors::v1_write::handle<PurgeRecycledEvent>", {
|
||||
let res = idms_prox_write
|
||||
.qs_write
|
||||
.purge_recycled()
|
||||
|
@ -1333,7 +1230,6 @@ impl QueryServerWriteV1 {
|
|||
admin_info!(?res, "Purge recycled result");
|
||||
#[allow(clippy::expect_used)]
|
||||
res.expect("Invalid Server State");
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) async fn handle_delayedaction(&self, da: DelayedAction) {
|
||||
|
@ -1344,13 +1240,11 @@ impl QueryServerWriteV1 {
|
|||
trace!("Begin delayed action ...");
|
||||
let ct = duration_from_epoch_now();
|
||||
let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
|
||||
spanned!("actors::v1_write::handle<DelayedAction>", {
|
||||
if let Err(res) = idms_prox_write
|
||||
.process_delayedaction(da)
|
||||
.and_then(|_| idms_prox_write.commit())
|
||||
{
|
||||
admin_info!(?res, "delayed action error");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
include!("./audit_loglevel.rs");
|
||||
|
||||
pub const AUDIT_LINE_SIZE: usize = 512;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use crate::be::dbvalue::{DbValueEmailAddressV1, DbValuePhoneNumberV1, DbValueSetV2, DbValueV1};
|
||||
use crate::prelude::OperationError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::be::dbvalue::{DbValueEmailAddressV1, DbValuePhoneNumberV1, DbValueSetV2, DbValueV1};
|
||||
use crate::prelude::OperationError;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DbEntryV1 {
|
||||
pub attrs: BTreeMap<AttrString, Vec<DbValueV1>>,
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use hashbrown::HashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{
|
||||
DeviceKey as DeviceKeyV4, Passkey as PasskeyV4, SecurityKey as SecurityKeyV4,
|
||||
};
|
||||
use webauthn_rs_core::proto::{COSEKey, UserVerificationPolicy};
|
||||
|
||||
use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
use webauthn_rs::prelude::SecurityKey as SecurityKeyV4;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DbCidV1 {
|
||||
#[serde(rename = "d")]
|
||||
|
@ -556,11 +556,11 @@ impl DbValueSetV2 {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::DbCred;
|
||||
use super::{DbBackupCodeV1, DbPasswordV1, DbTotpV1, DbWebauthnV1};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{DbBackupCodeV1, DbCred, DbPasswordV1, DbTotpV1, DbWebauthnV1};
|
||||
|
||||
fn dbcred_type_default_pw() -> DbCredTypeV1 {
|
||||
DbCredTypeV1::Pw
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn, ARCacheWriteTxn};
|
||||
use concread::cowcell::*;
|
||||
use hashbrown::HashMap;
|
||||
use idlset::v2::IDLBitRange;
|
||||
use idlset::AndNot;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::be::idl_sqlite::{
|
||||
IdlSqlite, IdlSqliteReadTransaction, IdlSqliteTransaction, IdlSqliteWriteTransaction,
|
||||
};
|
||||
|
@ -6,24 +21,8 @@ use crate::be::idxkey::{
|
|||
};
|
||||
use crate::be::{BackendConfig, IdList, IdRawEntry};
|
||||
use crate::entry::{Entry, EntryCommitted, EntrySealed};
|
||||
use crate::value::IndexType;
|
||||
use crate::value::Value;
|
||||
|
||||
use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn, ARCacheWriteTxn};
|
||||
use concread::cowcell::*;
|
||||
use idlset::{v2::IDLBitRange, AndNot};
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::prelude::*;
|
||||
use tracing::trace;
|
||||
use crate::value::{IndexType, Value};
|
||||
|
||||
// use std::borrow::Borrow;
|
||||
|
||||
|
@ -82,7 +81,6 @@ macro_rules! get_identry {
|
|||
$idl:expr,
|
||||
$is_read_op:expr
|
||||
) => {{
|
||||
spanned!("be::idl_arc_sqlite::get_identry", {
|
||||
let mut result: Vec<Arc<EntrySealedCommitted>> = Vec::new();
|
||||
match $idl {
|
||||
IdList::Partial(idli) | IdList::PartialThreshold(idli) | IdList::Indexed(idli) => {
|
||||
|
@ -133,7 +131,6 @@ macro_rules! get_identry {
|
|||
};
|
||||
// Return
|
||||
Ok(result)
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -165,7 +162,6 @@ macro_rules! get_idl {
|
|||
$itype:expr,
|
||||
$idx_key:expr
|
||||
) => {{
|
||||
spanned!("be::idl_arc_sqlite::get_idl", {
|
||||
// SEE ALSO #259: Find a way to implement borrow for this properly.
|
||||
// I don't think this is possible. When we make this dyn, the arc
|
||||
// needs the dyn trait to be sized so that it *could* claim a clone
|
||||
|
@ -188,10 +184,9 @@ macro_rules! get_idl {
|
|||
// If hit, continue.
|
||||
if let Some(ref data) = cache_r {
|
||||
trace!(
|
||||
%data,
|
||||
"Got cached idl for index {:?} {:?}",
|
||||
$itype,
|
||||
$attr,
|
||||
cached_index = ?$itype,
|
||||
attr = ?$attr,
|
||||
idl = %data,
|
||||
);
|
||||
return Ok(Some(data.as_ref().clone()));
|
||||
}
|
||||
|
@ -206,7 +201,6 @@ macro_rules! get_idl {
|
|||
$self.idl_cache.insert(ncache_key, Box::new(idl.clone()))
|
||||
}
|
||||
Ok(db_r)
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -215,7 +209,6 @@ macro_rules! name2uuid {
|
|||
$self:expr,
|
||||
$name:expr
|
||||
) => {{
|
||||
spanned!("be::idl_arc_sqlite::name2uuid", {
|
||||
let cache_key = NameCacheKey::Name2Uuid($name.to_string());
|
||||
let cache_r = $self.name_cache.get(&cache_key);
|
||||
if let Some(NameCacheValue::U(uuid)) = cache_r {
|
||||
|
@ -232,7 +225,6 @@ macro_rules! name2uuid {
|
|||
.insert(cache_key, NameCacheValue::U(uuid.clone()))
|
||||
}
|
||||
Ok(db_r)
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -241,7 +233,6 @@ macro_rules! uuid2spn {
|
|||
$self:expr,
|
||||
$uuid:expr
|
||||
) => {{
|
||||
spanned!("be::idl_arc_sqlite::uuid2spn", {
|
||||
let cache_key = NameCacheKey::Uuid2Spn($uuid);
|
||||
let cache_r = $self.name_cache.get(&cache_key);
|
||||
if let Some(NameCacheValue::S(ref spn)) = cache_r {
|
||||
|
@ -258,7 +249,6 @@ macro_rules! uuid2spn {
|
|||
.insert(cache_key, NameCacheValue::S(Box::new(data.clone())))
|
||||
}
|
||||
Ok(db_r)
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -267,7 +257,6 @@ macro_rules! uuid2rdn {
|
|||
$self:expr,
|
||||
$uuid:expr
|
||||
) => {{
|
||||
spanned!("be::idl_arc_sqlite::uuid2rdn", {
|
||||
let cache_key = NameCacheKey::Uuid2Rdn($uuid);
|
||||
let cache_r = $self.name_cache.get(&cache_key);
|
||||
if let Some(NameCacheValue::R(ref rdn)) = cache_r {
|
||||
|
@ -283,7 +272,6 @@ macro_rules! uuid2rdn {
|
|||
.insert(cache_key, NameCacheValue::R(data.clone()))
|
||||
}
|
||||
Ok(db_r)
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -528,8 +516,8 @@ impl<'a> IdlArcSqliteTransaction for IdlArcSqliteWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
||||
#[instrument(level = "debug", name = "idl_arc_sqlite::commit", skip_all)]
|
||||
pub fn commit(self) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_arc_sqlite::commit", {
|
||||
let IdlArcSqliteWriteTransaction {
|
||||
db,
|
||||
mut entry_cache,
|
||||
|
@ -541,21 +529,20 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
} = self;
|
||||
|
||||
// Write any dirty items to the disk.
|
||||
spanned!("be::idl_arc_sqlite::commit<entry>", {
|
||||
entry_cache
|
||||
.iter_mut_mark_clean()
|
||||
.try_for_each(|(k, v)| match v {
|
||||
Some(e) => db.write_identry(e),
|
||||
None => db.delete_identry(*k),
|
||||
})
|
||||
})
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Failed to sync entry cache to sqlite");
|
||||
e
|
||||
})?;
|
||||
|
||||
spanned!("be::idl_arc_sqlite::commit<idl>", {
|
||||
idl_cache.iter_mut_mark_clean().try_for_each(|(k, v)| {
|
||||
idl_cache
|
||||
.iter_mut_mark_clean()
|
||||
.try_for_each(|(k, v)| {
|
||||
match v {
|
||||
Some(idl) => db.write_idl(k.a.as_str(), k.i, k.k.as_str(), idl),
|
||||
#[allow(clippy::unreachable)]
|
||||
|
@ -570,13 +557,11 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Failed to sync idl cache to sqlite");
|
||||
e
|
||||
})?;
|
||||
|
||||
spanned!("be::idl_arc_sqlite::commit<names>", {
|
||||
name_cache
|
||||
.iter_mut_mark_clean()
|
||||
.try_for_each(|(k, v)| match (k, v) {
|
||||
|
@ -595,7 +580,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
|
||||
_ => Err(OperationError::InvalidCacheState),
|
||||
})
|
||||
})
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Failed to sync name cache to sqlite");
|
||||
e
|
||||
|
@ -610,7 +594,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
allids.commit();
|
||||
maxid.commit();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_id2entry_max_id(&self) -> Result<u64, OperationError> {
|
||||
|
@ -626,7 +609,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
where
|
||||
I: Iterator<Item = &'b Entry<EntrySealed, EntryCommitted>>,
|
||||
{
|
||||
spanned!("be::idl_arc_sqlite::write_identries", {
|
||||
entries.try_for_each(|e| {
|
||||
trace!("Inserting {:?} to cache", e.get_id());
|
||||
if e.get_id() == 0 {
|
||||
|
@ -638,7 +620,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
Ok(())
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_identries_raw<I>(&mut self, entries: I) -> Result<(), OperationError>
|
||||
|
@ -661,7 +642,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
where
|
||||
I: Iterator<Item = u64>,
|
||||
{
|
||||
spanned!("be::idl_arc_sqlite::delete_identry", {
|
||||
idl.try_for_each(|i| {
|
||||
trace!("Removing {:?} from cache", i);
|
||||
if i == 0 {
|
||||
|
@ -672,7 +652,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
Ok(())
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_idl(
|
||||
|
@ -682,7 +661,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
idx_key: &str,
|
||||
idl: &IDLBitRange,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_arc_sqlite::write_idl", {
|
||||
let cache_key = IdlCacheKey {
|
||||
a: attr.into(),
|
||||
i: itype,
|
||||
|
@ -700,14 +678,13 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
}
|
||||
// self.db.write_idl(audit, attr, itype, idx_key, idl)
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn optimise_dirty_idls(&mut self) {
|
||||
self.idl_cache.iter_mut_dirty().for_each(|(k, maybe_idl)| {
|
||||
if let Some(idl) = maybe_idl {
|
||||
if idl.maybe_compress() {
|
||||
filter_trace!(?k, "Compressed idl");
|
||||
trace!(?k, "Compressed idl");
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -971,27 +948,21 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
uuid: Uuid,
|
||||
add: BTreeSet<String>,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_arc_sqlite::write_name2uuid_add", {
|
||||
add.into_iter().for_each(|k| {
|
||||
let cache_key = NameCacheKey::Name2Uuid(k);
|
||||
let cache_value = NameCacheValue::U(uuid);
|
||||
self.name_cache.insert_dirty(cache_key, cache_value)
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_name2uuid_rem(&mut self, rem: BTreeSet<String>) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_arc_sqlite::write_name2uuid_rem", {
|
||||
// self.db.write_name2uuid_rem(audit, &rem).and_then(|_| {
|
||||
rem.into_iter().for_each(|k| {
|
||||
// why not just a for loop here...
|
||||
let cache_key = NameCacheKey::Name2Uuid(k);
|
||||
self.name_cache.remove_dirty(cache_key)
|
||||
});
|
||||
Ok(())
|
||||
// })
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_uuid2spn(&self) -> Result<(), OperationError> {
|
||||
|
@ -999,7 +970,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
pub fn write_uuid2spn(&mut self, uuid: Uuid, k: Option<Value>) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_arc_sqlite::write_uuid2spn", {
|
||||
let cache_key = NameCacheKey::Uuid2Spn(uuid);
|
||||
match k {
|
||||
Some(v) => self
|
||||
|
@ -1008,7 +978,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
None => self.name_cache.remove_dirty(cache_key),
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_uuid2rdn(&self) -> Result<(), OperationError> {
|
||||
|
@ -1016,7 +985,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
pub fn write_uuid2rdn(&mut self, uuid: Uuid, k: Option<String>) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_arc_sqlite::write_uuid2rdn", {
|
||||
let cache_key = NameCacheKey::Uuid2Rdn(uuid);
|
||||
match k {
|
||||
Some(s) => self
|
||||
|
@ -1025,7 +993,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
None => self.name_cache.remove_dirty(cache_key),
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_idx(&self, attr: &str, itype: IndexType) -> Result<(), OperationError> {
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
use crate::be::dbentry::DbEntry;
|
||||
use crate::be::dbentry::DbIdentSpn;
|
||||
use crate::be::{BackendConfig, IdList, IdRawEntry, IdxKey, IdxSlope};
|
||||
use crate::entry::{Entry, EntryCommitted, EntrySealed};
|
||||
use crate::prelude::*;
|
||||
use crate::value::{IndexType, Value};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
// use crate::valueset;
|
||||
use hashbrown::HashMap;
|
||||
use idlset::v2::IDLBitRange;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use rusqlite::Connection;
|
||||
use rusqlite::OpenFlags;
|
||||
use rusqlite::OptionalExtension;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tracing::trace;
|
||||
use rusqlite::{Connection, OpenFlags, OptionalExtension};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::be::dbentry::{DbEntry, DbIdentSpn};
|
||||
use crate::be::{BackendConfig, IdList, IdRawEntry, IdxKey, IdxSlope};
|
||||
use crate::entry::{Entry, EntryCommitted, EntrySealed};
|
||||
use crate::prelude::*;
|
||||
use crate::value::{IndexType, Value};
|
||||
|
||||
// use uuid::Uuid;
|
||||
|
||||
const DBV_ID2ENTRY: &str = "id2entry";
|
||||
|
@ -117,12 +115,10 @@ pub trait IdlSqliteTransaction {
|
|||
fn get_conn(&self) -> &r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
||||
|
||||
fn get_identry(&self, idl: &IdList) -> Result<Vec<Arc<EntrySealedCommitted>>, OperationError> {
|
||||
spanned!("be::idl_sqlite::get_identry", {
|
||||
self.get_identry_raw(idl)?
|
||||
.into_iter()
|
||||
.map(|ide| ide.into_entry().map(Arc::new))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn get_identry_raw(&self, idl: &IdList) -> Result<Vec<IdRawEntry>, OperationError> {
|
||||
|
@ -220,7 +216,6 @@ pub trait IdlSqliteTransaction {
|
|||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
) -> Result<Option<IDLBitRange>, OperationError> {
|
||||
spanned!("be::idl_sqlite::get_idl", {
|
||||
if !(self.exists_idx(attr, itype)?) {
|
||||
filter_error!(
|
||||
"IdlSqliteTransaction: Index {:?} {:?} not found",
|
||||
|
@ -252,14 +247,17 @@ pub trait IdlSqliteTransaction {
|
|||
// have a corrupted index .....
|
||||
None => IDLBitRange::new(),
|
||||
};
|
||||
trace!(%idl, "Got idl for index {:?} {:?}", itype, attr);
|
||||
|
||||
trace!(
|
||||
miss_index = ?itype,
|
||||
attr = ?attr,
|
||||
idl = %idl,
|
||||
);
|
||||
|
||||
Ok(Some(idl))
|
||||
})
|
||||
}
|
||||
|
||||
fn name2uuid(&mut self, name: &str) -> Result<Option<Uuid>, OperationError> {
|
||||
spanned!("be::idl_sqlite::name2uuid", {
|
||||
// The table exists - lets now get the actual index itself.
|
||||
let mut stmt = self
|
||||
.get_conn()
|
||||
|
@ -272,14 +270,11 @@ pub trait IdlSqliteTransaction {
|
|||
.map_err(sqlite_error)?;
|
||||
|
||||
let uuid = uuid_raw.as_ref().and_then(|u| Uuid::parse_str(u).ok());
|
||||
trace!(%name, ?uuid, "Got uuid for index");
|
||||
|
||||
Ok(uuid)
|
||||
})
|
||||
}
|
||||
|
||||
fn uuid2spn(&mut self, uuid: Uuid) -> Result<Option<Value>, OperationError> {
|
||||
spanned!("be::idl_sqlite::uuid2spn", {
|
||||
let uuids = uuid.as_hyphenated().to_string();
|
||||
// The table exists - lets now get the actual index itself.
|
||||
let mut stmt = self
|
||||
|
@ -302,14 +297,10 @@ pub trait IdlSqliteTransaction {
|
|||
None => None,
|
||||
};
|
||||
|
||||
trace!(?uuid, ?spn, "Got spn for uuid");
|
||||
|
||||
Ok(spn)
|
||||
})
|
||||
}
|
||||
|
||||
fn uuid2rdn(&mut self, uuid: Uuid) -> Result<Option<String>, OperationError> {
|
||||
spanned!("be::idl_sqlite::uuid2rdn", {
|
||||
let uuids = uuid.as_hyphenated().to_string();
|
||||
// The table exists - lets now get the actual index itself.
|
||||
let mut stmt = self
|
||||
|
@ -322,10 +313,7 @@ pub trait IdlSqliteTransaction {
|
|||
.optional()
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
trace!(?uuid, ?rdn, "Got rdn for uuid");
|
||||
|
||||
Ok(rdn)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_db_s_uuid(&self) -> Result<Option<Uuid>, OperationError> {
|
||||
|
@ -422,8 +410,8 @@ pub trait IdlSqliteTransaction {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "idl_sqlite::get_allids", skip_all)]
|
||||
fn get_allids(&self) -> Result<IDLBitRange, OperationError> {
|
||||
trace!("Building allids...");
|
||||
let mut stmt = self
|
||||
.get_conn()
|
||||
.prepare("SELECT id FROM id2entry")
|
||||
|
@ -604,9 +592,8 @@ impl IdlSqliteWriteTransaction {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "idl_sqlite::commit", skip_all)]
|
||||
pub fn commit(mut self) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_sqlite::commit", {
|
||||
trace!("Commiting BE WR txn");
|
||||
assert!(!self.committed);
|
||||
self.committed = true;
|
||||
|
||||
|
@ -617,7 +604,6 @@ impl IdlSqliteWriteTransaction {
|
|||
admin_error!(?e, "CRITICAL: failed to commit sqlite txn");
|
||||
OperationError::BackendEngine
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_id2entry_max_id(&self) -> Result<u64, OperationError> {
|
||||
|
@ -770,9 +756,7 @@ impl IdlSqliteWriteTransaction {
|
|||
idx_key: &str,
|
||||
idl: &IDLBitRange,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("be::idl_sqlite::write_idl", {
|
||||
if idl.is_empty() {
|
||||
trace!(?idl, "purging idl");
|
||||
// delete it
|
||||
// Delete this idx_key from the table.
|
||||
let query = format!(
|
||||
|
@ -786,7 +770,6 @@ impl IdlSqliteWriteTransaction {
|
|||
.and_then(|mut stmt| stmt.execute(&[(":key", &idx_key)]))
|
||||
.map_err(sqlite_error)
|
||||
} else {
|
||||
trace!(?idl, "writing idl");
|
||||
// Serialise the IdList to Vec<u8>
|
||||
let idl_raw = serde_json::to_vec(idl).map_err(serde_json_error)?;
|
||||
|
||||
|
@ -809,7 +792,6 @@ impl IdlSqliteWriteTransaction {
|
|||
}
|
||||
// Get rid of the sqlite rows usize
|
||||
.map(|_| ())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_name2uuid(&self) -> Result<(), OperationError> {
|
||||
|
@ -944,7 +926,7 @@ impl IdlSqliteWriteTransaction {
|
|||
itype.as_idx_str(),
|
||||
attr
|
||||
);
|
||||
trace!(idx = %idx_stmt, "Creating index");
|
||||
trace!(idx = %idx_stmt, "creating index");
|
||||
|
||||
self.conn
|
||||
.execute(idx_stmt.as_str(), [])
|
||||
|
@ -1034,7 +1016,6 @@ impl IdlSqliteWriteTransaction {
|
|||
}
|
||||
|
||||
pub unsafe fn purge_id2entry(&self) -> Result<(), OperationError> {
|
||||
trace!("purge id2entry ...");
|
||||
self.conn
|
||||
.execute("DELETE FROM id2entry", [])
|
||||
.map(|_| ())
|
||||
|
@ -1175,7 +1156,6 @@ impl IdlSqliteWriteTransaction {
|
|||
|
||||
// If the table is empty, populate the versions as 0.
|
||||
let mut dbv_id2entry = self.get_db_version_key(DBV_ID2ENTRY);
|
||||
trace!(initial = %dbv_id2entry, "dbv_id2entry");
|
||||
|
||||
// Check db_version here.
|
||||
// * if 0 -> create v1.
|
||||
|
@ -1374,13 +1354,12 @@ impl IdlSqlite {
|
|||
}
|
||||
|
||||
pub(crate) fn get_allids_count(&self) -> Result<u64, OperationError> {
|
||||
trace!("Counting allids...");
|
||||
#[allow(clippy::expect_used)]
|
||||
self.pool
|
||||
.try_get()
|
||||
.expect("Unable to get connection from pool!!!")
|
||||
.query_row("select count(id) from id2entry", [], |row| row.get(0))
|
||||
.map_err(sqlite_error) // this was initially `ltrace`, but I think that was a mistake so I replaced it anyways.
|
||||
.map_err(sqlite_error)
|
||||
}
|
||||
|
||||
pub fn read(&self) -> IdlSqliteReadTransaction {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use crate::value::IndexType;
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use smartstring::alias::String as AttrString;
|
||||
|
||||
use crate::value::IndexType;
|
||||
|
||||
pub type IdxSlope = u8;
|
||||
|
||||
// Huge props to https://github.com/sunshowers/borrow-complex-key-example/blob/master/src/lib.rs
|
||||
|
|
|
@ -4,35 +4,32 @@
|
|||
//! is to persist content safely to disk, load that content, and execute queries
|
||||
//! utilising indexes in the most effective way possible.
|
||||
|
||||
use std::fs;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::value::IndexType;
|
||||
use hashbrown::HashMap as Map;
|
||||
use hashbrown::HashSet;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::fs;
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use concread::cowcell::*;
|
||||
use hashbrown::{HashMap as Map, HashSet};
|
||||
use idlset::v2::IDLBitRange;
|
||||
use idlset::AndNot;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use tracing::{trace, trace_span};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::be::dbentry::{DbBackup, DbEntry};
|
||||
use crate::entry::{Entry, EntryCommitted, EntryNew, EntrySealed};
|
||||
use crate::filter::{Filter, FilterPlan, FilterResolved, FilterValidResolved};
|
||||
use crate::identity::Limits;
|
||||
use crate::value::Value;
|
||||
use concread::cowcell::*;
|
||||
use idlset::v2::IDLBitRange;
|
||||
use idlset::AndNot;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::ops::DerefMut;
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
use crate::repl::ruv::{
|
||||
ReplicationUpdateVector, ReplicationUpdateVectorReadTransaction,
|
||||
ReplicationUpdateVectorTransaction, ReplicationUpdateVectorWriteTransaction,
|
||||
};
|
||||
use crate::value::{IndexType, Value};
|
||||
|
||||
pub mod dbentry;
|
||||
pub mod dbvalue;
|
||||
|
@ -41,12 +38,10 @@ mod idl_sqlite;
|
|||
pub(crate) mod idxkey;
|
||||
|
||||
pub(crate) use self::idxkey::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxSlope};
|
||||
|
||||
use crate::be::idl_arc_sqlite::{
|
||||
IdlArcSqlite, IdlArcSqliteReadTransaction, IdlArcSqliteTransaction,
|
||||
IdlArcSqliteWriteTransaction,
|
||||
};
|
||||
|
||||
// Re-export this
|
||||
pub use crate::be::idl_sqlite::FsType;
|
||||
|
||||
|
@ -175,6 +170,7 @@ pub trait BackendTransaction {
|
|||
/// Recursively apply a filter, transforming into IdList's on the way. This builds a query
|
||||
/// execution log, so that it can be examined how an operation proceeded.
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
#[instrument(level = "debug", name = "be::filter2idl", skip_all)]
|
||||
fn filter2idl(
|
||||
&self,
|
||||
filt: &FilterResolved,
|
||||
|
@ -534,6 +530,7 @@ pub trait BackendTransaction {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "be::search", skip_all)]
|
||||
fn search(
|
||||
&self,
|
||||
erl: &Limits,
|
||||
|
@ -543,16 +540,12 @@ pub trait BackendTransaction {
|
|||
// Unlike DS, even if we don't get the index back, we can just pass
|
||||
// to the in-memory filter test and be done.
|
||||
|
||||
spanned!("be::search", {
|
||||
filter_trace!(?filt, "filter optimized");
|
||||
debug!(filter_optimised = ?filt);
|
||||
|
||||
let (idl, fplan) = trace_span!("be::search -> filter2idl").in_scope(|| {
|
||||
spanned!("be::search -> filter2idl", {
|
||||
self.filter2idl(filt.to_inner(), FILTER_SEARCH_TEST_THRESHOLD)
|
||||
})
|
||||
})?;
|
||||
let (idl, fplan) = trace_span!("be::search -> filter2idl")
|
||||
.in_scope(|| self.filter2idl(filt.to_inner(), FILTER_SEARCH_TEST_THRESHOLD))?;
|
||||
|
||||
filter_trace!(?fplan, "filter executed plan");
|
||||
debug!(filter_executed_plan = ?fplan);
|
||||
|
||||
match &idl {
|
||||
IdList::AllIds => {
|
||||
|
@ -593,29 +586,23 @@ pub trait BackendTransaction {
|
|||
|
||||
let entries_filtered = match idl {
|
||||
IdList::AllIds => trace_span!("be::search<entry::ftest::allids>").in_scope(|| {
|
||||
spanned!("be::search<entry::ftest::allids>", {
|
||||
entries
|
||||
.into_iter()
|
||||
.filter(|e| e.entry_match_no_index(filt))
|
||||
.collect()
|
||||
})
|
||||
}),
|
||||
IdList::Partial(_) => {
|
||||
trace_span!("be::search<entry::ftest::partial>").in_scope(|| {
|
||||
IdList::Partial(_) => trace_span!("be::search<entry::ftest::partial>").in_scope(|| {
|
||||
entries
|
||||
.into_iter()
|
||||
.filter(|e| e.entry_match_no_index(filt))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}),
|
||||
IdList::PartialThreshold(_) => trace_span!("be::search<entry::ftest::thresh>")
|
||||
.in_scope(|| {
|
||||
spanned!("be::search<entry::ftest::thresh>", {
|
||||
entries
|
||||
.into_iter()
|
||||
.filter(|e| e.entry_match_no_index(filt))
|
||||
.collect()
|
||||
})
|
||||
}),
|
||||
// Since the index fully resolved, we can shortcut the filter test step here!
|
||||
IdList::Indexed(_) => {
|
||||
|
@ -632,37 +619,33 @@ pub trait BackendTransaction {
|
|||
}
|
||||
|
||||
Ok(entries_filtered)
|
||||
})
|
||||
}
|
||||
|
||||
/// Given a filter, assert some condition exists.
|
||||
/// Basically, this is a specialised case of search, where we don't need to
|
||||
/// load any candidates if they match. This is heavily used in uuid
|
||||
/// refint and attr uniqueness.
|
||||
#[instrument(level = "debug", name = "be::exists", skip_all)]
|
||||
fn exists(
|
||||
&self,
|
||||
erl: &Limits,
|
||||
filt: &Filter<FilterValidResolved>,
|
||||
) -> Result<bool, OperationError> {
|
||||
let _entered = trace_span!("be::exists").entered();
|
||||
spanned!("be::exists", {
|
||||
filter_trace!(?filt, "filter optimised");
|
||||
debug!(filter_optimised = ?filt);
|
||||
|
||||
// Using the indexes, resolve the IdList here, or AllIds.
|
||||
// Also get if the filter was 100% resolved or not.
|
||||
let (idl, fplan) = spanned!("be::exists -> filter2idl", {
|
||||
spanned!("be::exists -> filter2idl", {
|
||||
self.filter2idl(filt.to_inner(), FILTER_EXISTS_TEST_THRESHOLD)
|
||||
})
|
||||
})?;
|
||||
let (idl, fplan) = self.filter2idl(filt.to_inner(), FILTER_EXISTS_TEST_THRESHOLD)?;
|
||||
|
||||
filter_trace!(?fplan, "filter executed plan");
|
||||
debug!(filter_executed_plan = ?fplan);
|
||||
|
||||
// Apply limits to the IdList.
|
||||
match &idl {
|
||||
IdList::AllIds => {
|
||||
if !erl.unindexed_allow {
|
||||
admin_error!("filter (exists) is fully unindexed, and not allowed by resource limits");
|
||||
admin_error!(
|
||||
"filter (exists) is fully unindexed, and not allowed by resource limits"
|
||||
);
|
||||
return Err(OperationError::ResourceLimit);
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +674,7 @@ pub trait BackendTransaction {
|
|||
|
||||
// if not 100% resolved query, apply the filter test.
|
||||
let entries_filtered: Vec<_> =
|
||||
spanned!("be::exists -> entry_match_no_index", {
|
||||
trace_span!("be::exists<entry::ftest>").in_scope(|| {
|
||||
entries
|
||||
.into_iter()
|
||||
.filter(|e| e.entry_match_no_index(filt))
|
||||
|
@ -701,7 +684,6 @@ pub trait BackendTransaction {
|
|||
Ok(!entries_filtered.is_empty())
|
||||
}
|
||||
} // end match idl
|
||||
}) // end spanned
|
||||
}
|
||||
|
||||
fn verify(&self) -> Vec<Result<(), ConsistencyError>> {
|
||||
|
@ -878,6 +860,7 @@ pub trait BackendTransaction {
|
|||
|
||||
impl<'a> BackendTransaction for BackendReadTransaction<'a> {
|
||||
type IdlLayerType = IdlArcSqliteReadTransaction<'a>;
|
||||
type RuvType = ReplicationUpdateVectorReadTransaction<'a>;
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
fn get_idlayer(&self) -> &mut IdlArcSqliteReadTransaction<'a> {
|
||||
|
@ -895,8 +878,6 @@ impl<'a> BackendTransaction for BackendReadTransaction<'a> {
|
|||
unsafe { &mut (*self.idlayer.get()) }
|
||||
}
|
||||
|
||||
type RuvType = ReplicationUpdateVectorReadTransaction<'a>;
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
fn get_ruv(&self) -> &mut ReplicationUpdateVectorReadTransaction<'a> {
|
||||
unsafe { &mut (*self.ruv.get()) }
|
||||
|
@ -930,14 +911,13 @@ impl<'a> BackendReadTransaction<'a> {
|
|||
|
||||
impl<'a> BackendTransaction for BackendWriteTransaction<'a> {
|
||||
type IdlLayerType = IdlArcSqliteWriteTransaction<'a>;
|
||||
type RuvType = ReplicationUpdateVectorWriteTransaction<'a>;
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
fn get_idlayer(&self) -> &mut IdlArcSqliteWriteTransaction<'a> {
|
||||
unsafe { &mut (*self.idlayer.get()) }
|
||||
}
|
||||
|
||||
type RuvType = ReplicationUpdateVectorWriteTransaction<'a>;
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
fn get_ruv(&self) -> &mut ReplicationUpdateVectorWriteTransaction<'a> {
|
||||
unsafe { &mut (*self.ruv.get()) }
|
||||
|
@ -949,12 +929,12 @@ impl<'a> BackendTransaction for BackendWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
impl<'a> BackendWriteTransaction<'a> {
|
||||
#[instrument(level = "debug", name = "be::create", skip_all)]
|
||||
pub fn create(
|
||||
&self,
|
||||
cid: &Cid,
|
||||
entries: Vec<Entry<EntrySealed, EntryNew>>,
|
||||
) -> Result<Vec<Entry<EntrySealed, EntryCommitted>>, OperationError> {
|
||||
spanned!("be::create", {
|
||||
if entries.is_empty() {
|
||||
admin_error!("No entries provided to BE to create, invalid server call!");
|
||||
return Err(OperationError::EmptyRequest);
|
||||
|
@ -1001,16 +981,15 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
Ok(c_entries)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "be::modify", skip_all)]
|
||||
pub fn modify(
|
||||
&self,
|
||||
cid: &Cid,
|
||||
pre_entries: &[Arc<EntrySealedCommitted>],
|
||||
post_entries: &[EntrySealedCommitted],
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("be::modify", {
|
||||
if post_entries.is_empty() || pre_entries.is_empty() {
|
||||
admin_error!("No entries provided to BE to modify, invalid server call!");
|
||||
return Err(OperationError::EmptyRequest);
|
||||
|
@ -1043,11 +1022,10 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
.iter()
|
||||
.zip(post_entries.iter())
|
||||
.try_for_each(|(pre, post)| self.entry_index(Some(pre.as_ref()), Some(post)))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "be::reap_tombstones", skip_all)]
|
||||
pub fn reap_tombstones(&self, cid: &Cid) -> Result<usize, OperationError> {
|
||||
spanned!("be::reap_tombstones", {
|
||||
// We plan to clear the RUV up to this cid. So we need to build an IDL
|
||||
// of all the entries we need to examine.
|
||||
let idl = self.get_ruv().trim_up_to(cid).map_err(|e| {
|
||||
|
@ -1121,9 +1099,9 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
.try_for_each(|e| self.entry_index(Some(e), None))?;
|
||||
|
||||
Ok(sz)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "be::update_idxmeta", skip_all)]
|
||||
pub fn update_idxmeta(&mut self, idxkeys: Vec<IdxKey>) -> Result<(), OperationError> {
|
||||
if self.is_idx_slopeyness_generated()? {
|
||||
trace!("Indexing slopes available");
|
||||
|
@ -1522,9 +1500,9 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "be::ruv_rebuild", skip_all)]
|
||||
pub fn ruv_rebuild(&mut self) -> Result<(), OperationError> {
|
||||
// Rebuild the ruv!
|
||||
spanned!("server::ruv_rebuild", {
|
||||
// For now this has to read from all the entries in the DB, but in the future
|
||||
// we'll actually store this properly (?). If it turns out this is really fast
|
||||
// we may just rebuild this always on startup.
|
||||
|
@ -1540,7 +1518,6 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
self.get_ruv().rebuild(&entries)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn commit(self) -> Result<(), OperationError> {
|
||||
|
@ -1639,6 +1616,7 @@ fn get_idx_slope_default(ikey: &IdxKey) -> IdxSlope {
|
|||
|
||||
// In the future this will do the routing between the chosen backends etc.
|
||||
impl Backend {
|
||||
#[instrument(level = "debug", name = "be::new", skip_all)]
|
||||
pub fn new(
|
||||
mut cfg: BackendConfig,
|
||||
// path: &str,
|
||||
|
@ -1675,7 +1653,6 @@ impl Backend {
|
|||
let ruv = Arc::new(ReplicationUpdateVector::default());
|
||||
|
||||
// this has a ::memory() type, but will path == "" work?
|
||||
spanned!("be::new", {
|
||||
let idlayer = Arc::new(IdlArcSqlite::new(&cfg, vacuum)?);
|
||||
let be = Backend {
|
||||
cfg,
|
||||
|
@ -1708,7 +1685,6 @@ impl Backend {
|
|||
})?;
|
||||
|
||||
Ok(be)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_pool_size(&self) -> u32 {
|
||||
|
@ -1762,22 +1738,23 @@ impl Backend {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use idlset::v2::IDLBitRange;
|
||||
use std::fs;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use idlset::v2::IDLBitRange;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::super::entry::{Entry, EntryInit, EntryNew};
|
||||
use super::{
|
||||
Backend, BackendConfig, BackendTransaction, BackendWriteTransaction, IdList, OperationError,
|
||||
Backend, BackendConfig, BackendTransaction, BackendWriteTransaction, DbBackup, IdList,
|
||||
IdxKey, OperationError,
|
||||
};
|
||||
use super::{DbBackup, IdxKey};
|
||||
use crate::identity::Limits;
|
||||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
use crate::value::{IndexType, PartialValue, Value};
|
||||
use std::time::Duration;
|
||||
|
||||
lazy_static! {
|
||||
static ref CID_ZERO: Cid = unsafe { Cid::new_zero() };
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
//! These components should be "per server". Any "per domain" config should be in the system
|
||||
//! or domain entries that are able to be replicated.
|
||||
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use kanidm_proto::messages::ConsoleOutputMode;
|
||||
use rand::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct IntegrationTestConfig {
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
use crate::be::dbvalue::DbBackupCodeV1;
|
||||
use crate::be::dbvalue::{DbCred, DbPasswordV1};
|
||||
use hashbrown::HashMap as Map;
|
||||
use hashbrown::HashSet;
|
||||
use std::convert::TryFrom;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use hashbrown::{HashMap as Map, HashSet};
|
||||
use kanidm_proto::v1::{BackupCodesView, CredentialDetail, CredentialDetailType, OperationError};
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkcs5::pbkdf2_hmac;
|
||||
use openssl::sha::Sha512;
|
||||
use rand::prelude::*;
|
||||
use std::convert::TryFrom;
|
||||
use std::time::{Duration, Instant};
|
||||
use uuid::Uuid;
|
||||
|
||||
use webauthn_rs_core::proto::Credential as WebauthnCredential;
|
||||
use webauthn_rs_core::proto::CredentialV3;
|
||||
|
||||
use webauthn_rs::prelude::{AuthenticationResult, Passkey, SecurityKey};
|
||||
use webauthn_rs_core::proto::{Credential as WebauthnCredential, CredentialV3};
|
||||
|
||||
use crate::be::dbvalue::{DbBackupCodeV1, DbCred, DbPasswordV1};
|
||||
|
||||
pub mod policy;
|
||||
pub mod softlock;
|
||||
|
@ -234,12 +231,15 @@ impl BackupCodes {
|
|||
pub fn new(code_set: HashSet<String>) -> Self {
|
||||
BackupCodes { code_set }
|
||||
}
|
||||
|
||||
pub fn verify(&self, code_chal: &str) -> bool {
|
||||
self.code_set.contains(code_chal)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, code_chal: &str) -> bool {
|
||||
self.code_set.remove(code_chal)
|
||||
}
|
||||
|
||||
pub fn to_dbbackupcodev1(&self) -> DbBackupCodeV1 {
|
||||
DbBackupCodeV1 {
|
||||
code_set: self.code_set.clone(),
|
||||
|
@ -892,9 +892,10 @@ impl CredentialType {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::credential::policy::CryptoPolicy;
|
||||
use crate::credential::*;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[test]
|
||||
fn test_credential_simple() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::Password;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::Password;
|
||||
|
||||
const PBKDF2_MIN_NIST_COST: u64 = 10000;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use crate::be::dbvalue::{DbTotpAlgoV1, DbTotpV1};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use kanidm_proto::v1::{TotpAlgo as ProtoTotpAlgo, TotpSecret as ProtoTotp};
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::sign::Signer;
|
||||
use rand::prelude::*;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use kanidm_proto::v1::TotpAlgo as ProtoTotpAlgo;
|
||||
use kanidm_proto::v1::TotpSecret as ProtoTotp;
|
||||
use crate::be::dbvalue::{DbTotpAlgoV1, DbTotpV1};
|
||||
|
||||
// This is 64 bits of entropy, as the examples in https://tools.ietf.org/html/rfc6238 show.
|
||||
const SECRET_SIZE_BYTES: usize = 8;
|
||||
|
@ -192,9 +191,10 @@ impl Totp {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP};
|
||||
|
||||
#[test]
|
||||
fn hotp_basic() {
|
||||
let otp_sha1 = Totp::new(vec![0], 30, TotpAlgo::Sha1);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
//! This module contains cryptographic setup code, a long with what policy
|
||||
//! and ciphers we accept.
|
||||
|
||||
use crate::config::Configuration;
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
|
||||
|
||||
use crate::config::Configuration;
|
||||
|
||||
/// From the server configuration, generate an OpenSSL acceptor that we can use
|
||||
/// to build our sockets for https/ldaps.
|
||||
pub fn setup_tls(config: &Configuration) -> Result<Option<SslAcceptorBuilder>, ErrorStack> {
|
||||
|
|
|
@ -24,6 +24,26 @@
|
|||
//! [`filter`]: ../filter/index.html
|
||||
//! [`schema`]: ../schema/index.html
|
||||
|
||||
use std::cmp::Ordering;
|
||||
pub use std::collections::BTreeSet as Set;
|
||||
use std::collections::{BTreeMap as Map, BTreeMap, BTreeSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
use hashbrown::HashMap;
|
||||
use kanidm_proto::v1::{
|
||||
ConsistencyError, Entry as ProtoEntry, Filter as ProtoFilter, OperationError, SchemaError,
|
||||
};
|
||||
use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use time::OffsetDateTime;
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{DeviceKey as DeviceKeyV4, Passkey as PasskeyV4};
|
||||
|
||||
use crate::be::dbentry::{DbEntry, DbEntryV2, DbEntryVers};
|
||||
use crate::be::dbvalue::DbValueSetV2;
|
||||
use crate::be::{IdxKey, IdxSlope};
|
||||
use crate::credential::Credential;
|
||||
use crate::filter::{Filter, FilterInvalid, FilterResolved, FilterValidResolved};
|
||||
use crate::ldap::ldap_vattr_map;
|
||||
|
@ -32,33 +52,8 @@ use crate::prelude::*;
|
|||
use crate::repl::cid::Cid;
|
||||
use crate::repl::entry::EntryChangelog;
|
||||
use crate::schema::{SchemaAttribute, SchemaClass, SchemaTransaction};
|
||||
use crate::value::{IndexType, SyntaxType};
|
||||
use crate::value::{IntentTokenState, PartialValue, Session, Value};
|
||||
use crate::value::{IndexType, IntentTokenState, PartialValue, Session, SyntaxType, Value};
|
||||
use crate::valueset::{self, ValueSet};
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::be::dbentry::{DbEntry, DbEntryV2, DbEntryVers};
|
||||
use crate::be::dbvalue::DbValueSetV2;
|
||||
use crate::be::{IdxKey, IdxSlope};
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
use hashbrown::HashMap;
|
||||
use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap as Map;
|
||||
pub use std::collections::BTreeSet as Set;
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
|
||||
// use std::convert::TryFrom;
|
||||
// use std::str::FromStr;
|
||||
|
@ -222,7 +217,6 @@ pub(crate) fn compare_attrs(left: &Eattrs, right: &Eattrs) -> bool {
|
|||
/// [`schema`]: ../schema/index.html
|
||||
/// [`access`]: ../access/index.html
|
||||
/// [`event`]: ../event/index.html
|
||||
///
|
||||
pub struct Entry<VALID, STATE> {
|
||||
valid: VALID,
|
||||
state: STATE,
|
||||
|
@ -323,11 +317,11 @@ impl Entry<EntryInit, EntryNew> {
|
|||
|
||||
/// Given a proto entry in JSON formed as a serialised string, processed that string
|
||||
/// into an Entry.
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn from_proto_entry_str(
|
||||
es: &str,
|
||||
qs: &QueryServerWriteTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("from_proto_entry_str", {
|
||||
if cfg!(test) {
|
||||
if es.len() > 256 {
|
||||
let (dsp_es, _) = es.split_at(255);
|
||||
|
@ -345,7 +339,6 @@ impl Entry<EntryInit, EntryNew> {
|
|||
})?;
|
||||
// now call from_proto_entry
|
||||
Self::from_proto_entry(&pe, qs)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -2471,13 +2464,15 @@ impl From<&SchemaClass> for Entry<EntryInit, EntryNew> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeSet as Set;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use smartstring::alias::String as AttrString;
|
||||
|
||||
use crate::be::{IdxKey, IdxSlope};
|
||||
use crate::entry::{Entry, EntryInit, EntryInvalid, EntryNew};
|
||||
use crate::modify::{Modify, ModifyList};
|
||||
use crate::value::{IndexType, PartialValue, Value};
|
||||
use hashbrown::HashMap;
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::collections::BTreeSet as Set;
|
||||
|
||||
#[test]
|
||||
fn test_entry_basic() {
|
||||
|
|
|
@ -15,6 +15,21 @@
|
|||
//! with the operation, and a clear path to know how to transform events between
|
||||
//! various types.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
#[cfg(test)]
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{
|
||||
AuthCredential, AuthMech, AuthRequest, AuthStep, CreateRequest, DeleteRequest,
|
||||
Entry as ProtoEntry, ModifyList as ProtoModifyList, ModifyRequest, OperationError,
|
||||
SearchRequest, SearchResponse, WhoamiResponse,
|
||||
};
|
||||
use ldap3_proto::simple::LdapFilter;
|
||||
use uuid::Uuid;
|
||||
#[cfg(test)]
|
||||
use webauthn_rs::prelude::PublicKeyCredential;
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced};
|
||||
use crate::filter::{Filter, FilterInvalid, FilterValid};
|
||||
use crate::identity::Limits;
|
||||
|
@ -23,24 +38,6 @@ use crate::modify::{ModifyInvalid, ModifyList, ModifyValid};
|
|||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use crate::value::PartialValue;
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use kanidm_proto::v1::ModifyList as ProtoModifyList;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::{
|
||||
AuthCredential, AuthMech, AuthRequest, AuthStep, CreateRequest, DeleteRequest, ModifyRequest,
|
||||
SearchRequest, SearchResponse, WhoamiResponse,
|
||||
};
|
||||
|
||||
use ldap3_proto::simple::LdapFilter;
|
||||
use std::collections::BTreeSet;
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(test)]
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(test)]
|
||||
use webauthn_rs::prelude::PublicKeyCredential;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SearchResult {
|
||||
|
|
|
@ -8,28 +8,28 @@
|
|||
//! [`Filter`]: struct.Filter.html
|
||||
//! [`Entry`]: ../entry/struct.Entry.html
|
||||
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
use std::collections::BTreeSet;
|
||||
use std::hash::Hash;
|
||||
use std::iter;
|
||||
use std::num::NonZeroU8;
|
||||
|
||||
use concread::arcache::ARCacheReadTxn;
|
||||
use hashbrown::HashMap;
|
||||
#[cfg(test)]
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{Filter as ProtoFilter, OperationError, SchemaError};
|
||||
use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter};
|
||||
// use smartstring::alias::String as AttrString;
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::be::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxMeta, IdxSlope};
|
||||
use crate::identity::IdentityId;
|
||||
use crate::ldap::ldap_attr_filter_map;
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use crate::value::{IndexType, PartialValue};
|
||||
use concread::arcache::ARCacheReadTxn;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::v1::{OperationError, SchemaError};
|
||||
use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter};
|
||||
// use smartstring::alias::String as AttrString;
|
||||
use serde::Deserialize;
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
use std::collections::BTreeSet;
|
||||
use std::hash::Hash;
|
||||
use std::iter;
|
||||
use std::num::NonZeroU8;
|
||||
use uuid::Uuid;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
#[cfg(test)]
|
||||
use hashbrown::HashSet;
|
||||
|
||||
const FILTER_DEPTH_MAX: usize = 16;
|
||||
|
||||
|
@ -491,12 +491,12 @@ impl Filter<FilterInvalid> {
|
|||
// This has to have two versions to account for ro/rw traits, because RS can't
|
||||
// monomorphise on the trait to call clone_value. An option is to make a fn that
|
||||
// takes "clone_value(t, a, v) instead, but that may have a similar issue.
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn from_ro(
|
||||
ev: &Identity,
|
||||
f: &ProtoFilter,
|
||||
qs: &QueryServerReadTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("filer::from_ro", {
|
||||
let depth = FILTER_DEPTH_MAX;
|
||||
let mut elems = ev.limits.filter_max_elements;
|
||||
Ok(Filter {
|
||||
|
@ -504,15 +504,14 @@ impl Filter<FilterInvalid> {
|
|||
inner: FilterComp::from_ro(f, qs, depth, &mut elems)?,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn from_rw(
|
||||
ev: &Identity,
|
||||
f: &ProtoFilter,
|
||||
qs: &QueryServerWriteTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("filter::from_rw", {
|
||||
let depth = FILTER_DEPTH_MAX;
|
||||
let mut elems = ev.limits.filter_max_elements;
|
||||
Ok(Filter {
|
||||
|
@ -520,15 +519,14 @@ impl Filter<FilterInvalid> {
|
|||
inner: FilterComp::from_rw(f, qs, depth, &mut elems)?,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn from_ldap_ro(
|
||||
ev: &Identity,
|
||||
f: &LdapFilter,
|
||||
qs: &QueryServerReadTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("filter::from_ldap_ro", {
|
||||
let depth = FILTER_DEPTH_MAX;
|
||||
let mut elems = ev.limits.filter_max_elements;
|
||||
Ok(Filter {
|
||||
|
@ -536,7 +534,6 @@ impl Filter<FilterInvalid> {
|
|||
inner: FilterComp::from_ldap_ro(f, qs, depth, &mut elems)?,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -948,7 +945,6 @@ impl PartialOrd for FilterResolved {
|
|||
|
||||
impl Ord for FilterResolved {
|
||||
/// Ordering of filters for optimisation and subsequent dead term elimination.
|
||||
///
|
||||
fn cmp(&self, rhs: &FilterResolved) -> Ordering {
|
||||
let left_slopey = self.get_slopeyness_factor();
|
||||
let right_slopey = rhs.get_slopeyness_factor();
|
||||
|
@ -1330,10 +1326,6 @@ impl FilterResolved {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::event::CreateEvent;
|
||||
use crate::event::DeleteEvent;
|
||||
use crate::filter::{Filter, FilterInvalid, FILTER_DEPTH_MAX};
|
||||
use crate::prelude::*;
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
use std::collections::BTreeSet;
|
||||
use std::time::Duration;
|
||||
|
@ -1341,6 +1333,10 @@ mod tests {
|
|||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use ldap3_proto::simple::LdapFilter;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent};
|
||||
use crate::filter::{Filter, FilterInvalid, FILTER_DEPTH_MAX};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[test]
|
||||
fn test_filter_simple() {
|
||||
// Test construction.
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
//! and this provides the set of `Limits` to confine how many resources that the
|
||||
//! identity may consume during operations to prevent denial-of-service.
|
||||
|
||||
use crate::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeSet;
|
||||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Limits on the resources a single event can consume. These are defined per-event
|
||||
/// as they are derived from the userAuthToken based on that individual session
|
||||
|
|
|
@ -1,30 +1,27 @@
|
|||
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed};
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::UiHint;
|
||||
use kanidm_proto::v1::{AuthType, UserAuthToken};
|
||||
use kanidm_proto::v1::{BackupCodesView, CredentialStatus};
|
||||
|
||||
use webauthn_rs::prelude::CredentialID;
|
||||
use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
use kanidm_proto::v1::{
|
||||
AuthType, BackupCodesView, CredentialStatus, OperationError, UiHint, UserAuthToken,
|
||||
};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{
|
||||
AuthenticationResult, CredentialID, DeviceKey as DeviceKeyV4, Passkey as PasskeyV4,
|
||||
};
|
||||
|
||||
use crate::constants::UUID_ANONYMOUS;
|
||||
use crate::credential::policy::CryptoPolicy;
|
||||
use crate::credential::{softlock::CredSoftLockPolicy, Credential};
|
||||
use crate::credential::softlock::CredSoftLockPolicy;
|
||||
use crate::credential::Credential;
|
||||
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed};
|
||||
use crate::idm::group::Group;
|
||||
use crate::idm::server::IdmServerProxyWriteTransaction;
|
||||
use crate::modify::{ModifyInvalid, ModifyList};
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use crate::value::{IntentTokenState, PartialValue, Value};
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::AuthenticationResult;
|
||||
|
||||
lazy_static! {
|
||||
static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account");
|
||||
static ref PVCLASS_POSIXACCOUNT: PartialValue = PartialValue::new_class("posixaccount");
|
||||
|
@ -153,34 +150,31 @@ pub(crate) struct Account {
|
|||
}
|
||||
|
||||
impl Account {
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub(crate) fn try_from_entry_ro(
|
||||
value: &Entry<EntrySealed, EntryCommitted>,
|
||||
qs: &mut QueryServerReadTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("idm::account::try_from_entry_ro", {
|
||||
let groups = Group::try_from_account_entry_ro(value, qs)?;
|
||||
try_from_entry!(value, groups)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub(crate) fn try_from_entry_rw(
|
||||
value: &Entry<EntrySealed, EntryCommitted>,
|
||||
qs: &mut QueryServerWriteTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("idm::account::try_from_entry_rw", {
|
||||
let groups = Group::try_from_account_entry_rw(value, qs)?;
|
||||
try_from_entry!(value, groups)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub(crate) fn try_from_entry_reduced(
|
||||
value: &Entry<EntryReduced, EntryCommitted>,
|
||||
qs: &mut QueryServerReadTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("idm::account::try_from_entry_reduced", {
|
||||
let groups = Group::try_from_account_entry_red_ro(value, qs)?;
|
||||
try_from_entry!(value, groups)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn try_from_entry_no_groups(
|
||||
|
|
|
@ -2,34 +2,32 @@
|
|||
//! Generally this has to process an authentication attempt, and validate each
|
||||
//! factor to assert that the user is legitimate. This also contains some
|
||||
//! support code for asynchronous task execution.
|
||||
use crate::credential::BackupCodes;
|
||||
use crate::idm::account::Account;
|
||||
use crate::idm::delayed::BackupCodeRemoval;
|
||||
use crate::idm::AuthState;
|
||||
use crate::prelude::*;
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech, AuthType};
|
||||
|
||||
use crate::credential::{totp::Totp, Credential, CredentialType, Password};
|
||||
|
||||
use crate::idm::delayed::{DelayedAction, PasswordUpgrade, WebauthnCounterIncrement};
|
||||
// use crossbeam::channel::Sender;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
// use webauthn_rs::proto::Credential as WebauthnCredential;
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use std::collections::BTreeMap;
|
||||
pub use std::collections::BTreeSet as Set;
|
||||
use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
|
||||
// use webauthn_rs::proto::Credential as WebauthnCredential;
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech, AuthType, OperationError};
|
||||
// use crossbeam::channel::Sender;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use uuid::Uuid;
|
||||
// use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
use webauthn_rs::prelude::{
|
||||
PasskeyAuthentication, RequestChallengeResponse, SecurityKeyAuthentication, Webauthn,
|
||||
};
|
||||
// use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
|
||||
use crate::credential::totp::Totp;
|
||||
use crate::credential::{BackupCodes, Credential, CredentialType, Password};
|
||||
use crate::idm::account::Account;
|
||||
use crate::idm::delayed::{
|
||||
BackupCodeRemoval, DelayedAction, PasswordUpgrade, WebauthnCounterIncrement,
|
||||
};
|
||||
use crate::idm::AuthState;
|
||||
use crate::prelude::*;
|
||||
|
||||
// Each CredHandler takes one or more credentials and determines if the
|
||||
// handlers requirements can be 100% fufilled. This is where MFA or other
|
||||
|
@ -405,7 +403,9 @@ impl CredHandler {
|
|||
CredState::Denied(BAD_AUTH_TYPE_MSG)
|
||||
}
|
||||
}
|
||||
} // end CredHandler::PasswordMfa
|
||||
}
|
||||
|
||||
// end CredHandler::PasswordMfa
|
||||
|
||||
/// Validate a webauthn authentication attempt
|
||||
pub fn validate_webauthn(
|
||||
|
@ -832,6 +832,16 @@ impl AuthSession {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub use std::collections::BTreeSet as Set;
|
||||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech};
|
||||
use tokio::sync::mpsc::unbounded_channel as unbounded;
|
||||
use webauthn_authenticator_rs::softpasskey::SoftPasskey;
|
||||
use webauthn_authenticator_rs::WebauthnAuthenticator;
|
||||
|
||||
use crate::credential::policy::CryptoPolicy;
|
||||
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
|
||||
use crate::credential::{BackupCodes, Credential};
|
||||
|
@ -842,17 +852,7 @@ mod tests {
|
|||
use crate::idm::delayed::DelayedAction;
|
||||
use crate::idm::AuthState;
|
||||
use crate::prelude::*;
|
||||
use hashbrown::HashSet;
|
||||
pub use std::collections::BTreeSet as Set;
|
||||
|
||||
use crate::utils::{duration_from_epoch_now, readable_password_from_random};
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech};
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::sync::mpsc::unbounded_channel as unbounded;
|
||||
use webauthn_authenticator_rs::{softpasskey::SoftPasskey, WebauthnAuthenticator};
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
|
||||
fn create_pw_badlist_cache() -> HashSet<String> {
|
||||
let mut s = HashSet::new();
|
||||
|
|
|
@ -1,36 +1,28 @@
|
|||
use crate::access::AccessControlsTransaction;
|
||||
use crate::credential::{BackupCodes, Credential};
|
||||
use crate::idm::account::Account;
|
||||
use crate::idm::server::IdmServerCredUpdateTransaction;
|
||||
use crate::idm::server::IdmServerProxyWriteTransaction;
|
||||
use crate::prelude::*;
|
||||
use crate::value::IntentTokenState;
|
||||
use hashbrown::HashSet;
|
||||
use core::ops::Deref;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
CURegState, CUStatus, CredentialDetail, PasskeyDetail, PasswordFeedback, TotpSecret,
|
||||
};
|
||||
|
||||
use crate::utils::{backup_code_from_random, readable_password_from_random, uuid_from_duration};
|
||||
|
||||
use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::OffsetDateTime;
|
||||
use webauthn_rs::prelude::{
|
||||
CreationChallengeResponse, PasskeyRegistration, RegisterPublicKeyCredential,
|
||||
CreationChallengeResponse, DeviceKey as DeviceKeyV4, Passkey as PasskeyV4, PasskeyRegistration,
|
||||
RegisterPublicKeyCredential,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use core::ops::Deref;
|
||||
use crate::access::AccessControlsTransaction;
|
||||
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
|
||||
use crate::credential::{BackupCodes, Credential};
|
||||
use crate::idm::account::Account;
|
||||
use crate::idm::server::{IdmServerCredUpdateTransaction, IdmServerProxyWriteTransaction};
|
||||
use crate::prelude::*;
|
||||
use crate::utils::{backup_code_from_random, readable_password_from_random, uuid_from_duration};
|
||||
use crate::value::IntentTokenState;
|
||||
|
||||
const MAXIMUM_CRED_UPDATE_TTL: Duration = Duration::from_secs(900);
|
||||
const MAXIMUM_INTENT_TTL: Duration = Duration::from_secs(86400);
|
||||
|
@ -155,7 +147,6 @@ pub struct CredentialUpdateSessionStatus {
|
|||
// The target user's display name
|
||||
displayname: String,
|
||||
// ttl: Duration,
|
||||
//
|
||||
can_commit: bool,
|
||||
primary: Option<CredentialDetail>,
|
||||
passkeys: Vec<PasskeyDetail>,
|
||||
|
@ -384,12 +375,12 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
Ok((CredentialUpdateSessionToken { token_enc }, status))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn init_credential_update_intent(
|
||||
&mut self,
|
||||
event: &InitCredentialUpdateIntentEvent,
|
||||
ct: Duration,
|
||||
) -> Result<CredentialUpdateIntentToken, OperationError> {
|
||||
spanned!("idm::server::credupdatesession<Init>", {
|
||||
let account = self.validate_init_credential_update(event.target, &event.ident)?;
|
||||
|
||||
// ==== AUTHORISATION CHECKED ===
|
||||
|
@ -429,8 +420,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
);
|
||||
|
||||
// Remove any old credential update intents
|
||||
account.credential_update_intent_tokens.iter().for_each(
|
||||
|(existing_intent_id, state)| {
|
||||
account
|
||||
.credential_update_intent_tokens
|
||||
.iter()
|
||||
.for_each(|(existing_intent_id, state)| {
|
||||
let max_ttl = match state {
|
||||
IntentTokenState::Valid { max_ttl }
|
||||
| IntentTokenState::InProgress {
|
||||
|
@ -447,8 +440,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
PartialValue::IntentToken(existing_intent_id.clone()),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
self.qs_write
|
||||
.internal_modify(
|
||||
|
@ -462,7 +454,6 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
})?;
|
||||
|
||||
Ok(CredentialUpdateIntentToken { intent_id })
|
||||
})
|
||||
}
|
||||
|
||||
pub fn exchange_intent_credential_update(
|
||||
|
@ -642,12 +633,12 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
self.create_credupdate_session(session_id, Some(intent_id), account, current_time)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn init_credential_update(
|
||||
&mut self,
|
||||
event: &InitCredentialUpdateEvent,
|
||||
ct: Duration,
|
||||
) -> Result<(CredentialUpdateSessionToken, CredentialUpdateSessionStatus), OperationError> {
|
||||
spanned!("idm::server::credupdatesession<Init>", {
|
||||
let account = self.validate_init_credential_update(event.target, &event.ident)?;
|
||||
// ==== AUTHORISATION CHECKED ===
|
||||
// This is the expiry time, so that our cleanup task can "purge up to now" rather
|
||||
|
@ -656,7 +647,6 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
// Build the cred update session.
|
||||
self.create_credupdate_session(sessionid, None, account, ct)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
|
@ -1472,6 +1462,14 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use async_std::task;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthMech, CredentialDetailType};
|
||||
use uuid::uuid;
|
||||
use webauthn_authenticator_rs::softpasskey::SoftPasskey;
|
||||
use webauthn_authenticator_rs::WebauthnAuthenticator;
|
||||
|
||||
use super::{
|
||||
CredentialUpdateSessionStatus, CredentialUpdateSessionToken, InitCredentialUpdateEvent,
|
||||
InitCredentialUpdateIntentEvent, MfaRegStateStatus, MAXIMUM_CRED_UPDATE_TTL,
|
||||
|
@ -1481,16 +1479,8 @@ mod tests {
|
|||
use crate::event::{AuthEvent, AuthResult, CreateEvent};
|
||||
use crate::idm::delayed::DelayedAction;
|
||||
use crate::idm::server::IdmServer;
|
||||
use crate::prelude::*;
|
||||
use std::time::Duration;
|
||||
|
||||
use webauthn_authenticator_rs::{softpasskey::SoftPasskey, WebauthnAuthenticator};
|
||||
|
||||
use crate::idm::AuthState;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthMech, CredentialDetailType};
|
||||
use uuid::uuid;
|
||||
|
||||
use async_std::task;
|
||||
use crate::prelude::*;
|
||||
|
||||
const TEST_CURRENT_TIME: u64 = 6000;
|
||||
const TESTPERSON_UUID: Uuid = uuid!("cf231fea-1a8f-4410-a520-fd9b1a379c86");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) struct PasswordChangeEvent {
|
||||
pub ident: Identity,
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use kanidm_proto::v1::{Group as ProtoGroup, OperationError};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed};
|
||||
use crate::prelude::*;
|
||||
use crate::value::PartialValue;
|
||||
use kanidm_proto::v1::Group as ProtoGroup;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
lazy_static! {
|
||||
static ref PVCLASS_GROUP: PartialValue = PartialValue::new_class("group");
|
||||
|
|
|
@ -15,10 +15,10 @@ pub mod server;
|
|||
pub(crate) mod serviceaccount;
|
||||
pub(crate) mod unix;
|
||||
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthMech};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthMech};
|
||||
|
||||
pub enum AuthState {
|
||||
Choose(Vec<AuthMech>),
|
||||
Continue(Vec<AuthAllowed>),
|
||||
|
|
|
@ -3,30 +3,19 @@
|
|||
//! This contains the in memory and loaded set of active oauth2 resource server
|
||||
//! integrations, which are then able to be used an accessed from the IDM layer
|
||||
//! for operations involving oauth2 authentication processing.
|
||||
//!
|
||||
|
||||
use crate::identity::IdentityId;
|
||||
use crate::idm::delayed::{DelayedAction, Oauth2ConsentGrant};
|
||||
use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerTransaction};
|
||||
use crate::prelude::*;
|
||||
use crate::value::OAUTHSCOPE_RE;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
pub use compact_jwt::{JwkKeySet, OidcToken};
|
||||
use compact_jwt::{JwsSigner, OidcClaims, OidcSubject};
|
||||
use concread::cowcell::*;
|
||||
use fernet::Fernet;
|
||||
use hashbrown::HashMap;
|
||||
use kanidm_proto::v1::{AuthType, UserAuthToken};
|
||||
use openssl::sha;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use tracing::trace;
|
||||
use url::{Origin, Url};
|
||||
|
||||
pub use kanidm_proto::oauth2::{
|
||||
AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest,
|
||||
AccessTokenResponse, AuthorisationRequest, CodeChallengeMethod, ErrorResponse,
|
||||
|
@ -36,9 +25,19 @@ use kanidm_proto::oauth2::{
|
|||
ClaimType, DisplayValue, GrantType, IdTokenSignAlg, ResponseMode, ResponseType, SubjectType,
|
||||
TokenEndpointAuthMethod,
|
||||
};
|
||||
use kanidm_proto::v1::{AuthType, UserAuthToken};
|
||||
use openssl::sha;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use tracing::trace;
|
||||
use url::{Origin, Url};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
use crate::identity::IdentityId;
|
||||
use crate::idm::delayed::{DelayedAction, Oauth2ConsentGrant};
|
||||
use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerTransaction};
|
||||
use crate::prelude::*;
|
||||
use crate::value::OAUTHSCOPE_RE;
|
||||
|
||||
lazy_static! {
|
||||
static ref CLASS_OAUTH2: PartialValue = PartialValue::new_class("oauth2_resource_server");
|
||||
|
@ -1351,26 +1350,22 @@ fn parse_basic_authz(client_authz: &str) -> Result<(String, String), Oauth2Error
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::event::CreateEvent;
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use compact_jwt::{JwaAlg, Jwk, JwkUse, JwsValidator, OidcSubject, OidcUnverified};
|
||||
use kanidm_proto::oauth2::*;
|
||||
use kanidm_proto::v1::{AuthType, UserAuthToken};
|
||||
use openssl::sha;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::idm::delayed::DelayedAction;
|
||||
use crate::idm::oauth2::{AuthoriseResponse, Oauth2Error};
|
||||
use crate::idm::server::{IdmServer, IdmServerTransaction};
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::event::{DeleteEvent, ModifyEvent};
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use kanidm_proto::oauth2::*;
|
||||
use kanidm_proto::v1::{AuthType, UserAuthToken};
|
||||
|
||||
use compact_jwt::{JwaAlg, Jwk, JwkUse, JwsValidator, OidcSubject, OidcUnverified};
|
||||
|
||||
use openssl::sha;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
const TEST_CURRENT_TIME: u64 = 6000;
|
||||
const UAT_EXPIRE: u64 = 5;
|
||||
const TOKEN_EXPIRE: u64 = 900;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use crate::idm::group::Group;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{OperationError, RadiusAuthToken};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryReduced};
|
||||
use crate::idm::group::Group;
|
||||
use crate::prelude::*;
|
||||
use crate::value::PartialValue;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::RadiusAuthToken;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
lazy_static! {
|
||||
static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account");
|
||||
|
|
|
@ -1,3 +1,35 @@
|
|||
use core::task::{Context, Poll};
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_std::task;
|
||||
use compact_jwt::{Jws, JwsSigner, JwsUnverified, JwsValidator};
|
||||
use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn};
|
||||
use concread::cowcell::{CowCellReadTxn, CowCellWriteTxn};
|
||||
use concread::hashmap::HashMap;
|
||||
use concread::CowCell;
|
||||
use fernet::Fernet;
|
||||
// #[cfg(any(test,bench))]
|
||||
use futures::task as futures_task;
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, UnixGroupToken,
|
||||
UnixUserToken, UserAuthToken,
|
||||
};
|
||||
use rand::prelude::*;
|
||||
use tokio::sync::mpsc::{
|
||||
unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender,
|
||||
};
|
||||
use tokio::sync::{Mutex, Semaphore};
|
||||
use tracing::trace;
|
||||
use url::Url;
|
||||
use webauthn_rs::prelude::{Webauthn, WebauthnBuilder};
|
||||
|
||||
use super::delayed::BackupCodeRemoval;
|
||||
use super::event::ReadBackupCodeEvent;
|
||||
use crate::actors::v1_write::QueryServerWriteV1;
|
||||
use crate::credential::policy::CryptoPolicy;
|
||||
use crate::credential::softlock::CredSoftLock;
|
||||
use crate::event::{AuthEvent, AuthEventStep, AuthResult};
|
||||
|
@ -5,6 +37,10 @@ use crate::identity::{IdentType, IdentUser, Limits};
|
|||
use crate::idm::account::Account;
|
||||
use crate::idm::authsession::AuthSession;
|
||||
use crate::idm::credupdatesession::CredentialUpdateSessionMutex;
|
||||
use crate::idm::delayed::{
|
||||
DelayedAction, Oauth2ConsentGrant, PasswordUpgrade, UnixPasswordUpgrade,
|
||||
WebauthnCounterIncrement,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use crate::idm::event::PasswordChangeEvent;
|
||||
use crate::idm::event::{
|
||||
|
@ -26,54 +62,6 @@ use crate::ldap::{LdapBoundToken, LdapSession};
|
|||
use crate::prelude::*;
|
||||
use crate::utils::{password_from_random, readable_password_from_random, uuid_from_duration, Sid};
|
||||
|
||||
use crate::actors::v1_write::QueryServerWriteV1;
|
||||
use crate::idm::delayed::{
|
||||
DelayedAction, Oauth2ConsentGrant, PasswordUpgrade, UnixPasswordUpgrade,
|
||||
WebauthnCounterIncrement,
|
||||
};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, UnixGroupToken,
|
||||
UnixUserToken, UserAuthToken,
|
||||
};
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner, JwsUnverified, JwsValidator};
|
||||
use fernet::Fernet;
|
||||
|
||||
use tokio::sync::mpsc::{
|
||||
unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender,
|
||||
};
|
||||
use tokio::sync::Semaphore;
|
||||
|
||||
use async_std::task;
|
||||
|
||||
// #[cfg(any(test,bench))]
|
||||
use core::task::{Context, Poll};
|
||||
// #[cfg(any(test,bench))]
|
||||
use futures::task as futures_task;
|
||||
|
||||
use concread::{
|
||||
bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn},
|
||||
cowcell::{CowCellReadTxn, CowCellWriteTxn},
|
||||
hashmap::HashMap,
|
||||
CowCell,
|
||||
};
|
||||
|
||||
use rand::prelude::*;
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::sync::Mutex;
|
||||
use url::Url;
|
||||
|
||||
use webauthn_rs::prelude::{Webauthn, WebauthnBuilder};
|
||||
|
||||
use super::delayed::BackupCodeRemoval;
|
||||
use super::event::ReadBackupCodeEvent;
|
||||
|
||||
use tracing::trace;
|
||||
|
||||
type AuthSessionMutex = Arc<Mutex<AuthSession>>;
|
||||
type CredSoftLockMutex = Arc<Mutex<CredSoftLock>>;
|
||||
|
||||
|
@ -298,6 +286,7 @@ impl IdmServer {
|
|||
}
|
||||
|
||||
/// Read from the database, in a transaction.
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub async fn proxy_read_async(&self) -> IdmServerProxyReadTransaction<'_> {
|
||||
IdmServerProxyReadTransaction {
|
||||
qs_read: self.qs.read_async().await,
|
||||
|
@ -312,6 +301,7 @@ impl IdmServer {
|
|||
task::block_on(self.proxy_write_async(ts))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub async fn proxy_write_async(&self, ts: Duration) -> IdmServerProxyWriteTransaction<'_> {
|
||||
let mut sid = [0; 4];
|
||||
let mut rng = StdRng::from_entropy();
|
||||
|
@ -421,6 +411,7 @@ pub(crate) trait IdmServerTransaction<'a> {
|
|||
/// The primary method of verification selection is the use of the KID parameter
|
||||
/// that we internally sign with. We can use this to select the appropriate token type
|
||||
/// and validation method.
|
||||
#[instrument(level = "info", skip_all)]
|
||||
fn validate_and_parse_token_to_ident(
|
||||
&self,
|
||||
token: Option<&str>,
|
||||
|
@ -532,6 +523,7 @@ pub(crate) trait IdmServerTransaction<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn validate_and_parse_uat(
|
||||
&self,
|
||||
token: Option<&str>,
|
||||
|
@ -598,6 +590,7 @@ pub(crate) trait IdmServerTransaction<'a> {
|
|||
/// something we can pin access controls and other limits and references to.
|
||||
/// This is why it is the location where validity windows are checked and other
|
||||
/// relevant session information is injected.
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn process_uat_to_identity(
|
||||
&self,
|
||||
uat: &UserAuthToken,
|
||||
|
@ -663,6 +656,7 @@ pub(crate) trait IdmServerTransaction<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn process_apit_to_identity(
|
||||
&self,
|
||||
apit: &ApiToken,
|
||||
|
@ -683,6 +677,7 @@ pub(crate) trait IdmServerTransaction<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn validate_ldap_session(
|
||||
&self,
|
||||
session: &LdapSession,
|
||||
|
@ -883,7 +878,6 @@ impl<'a> IdmServerAuthTransaction<'a> {
|
|||
match auth_session {
|
||||
Some(auth_session) => {
|
||||
let mut session_write = self.sessions.write();
|
||||
spanned!("idm::server::auth<Init> -> sessions", {
|
||||
if session_write.contains_key(&sessionid) {
|
||||
Err(OperationError::InvalidSessionState)
|
||||
} else {
|
||||
|
@ -891,8 +885,7 @@ impl<'a> IdmServerAuthTransaction<'a> {
|
|||
// Debugging: ensure we really inserted ...
|
||||
debug_assert!(session_write.get(&sessionid).is_some());
|
||||
Ok(())
|
||||
}
|
||||
})?;
|
||||
}?;
|
||||
session_write.commit();
|
||||
}
|
||||
None => {
|
||||
|
@ -2024,8 +2017,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub fn commit(mut self) -> Result<(), OperationError> {
|
||||
spanned!("idm::server::IdmServerProxyWriteTransaction::commit", {
|
||||
if self
|
||||
.qs_write
|
||||
.get_changed_uuids()
|
||||
|
@ -2082,7 +2075,6 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
self.cred_update_sessions.commit();
|
||||
trace!("cred_update_session.commit");
|
||||
self.qs_write.commit()
|
||||
})
|
||||
}
|
||||
|
||||
fn reload_password_badlist(&mut self) -> Result<(), OperationError> {
|
||||
|
@ -2100,6 +2092,14 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_std::task;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthMech, AuthType, OperationError};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::credential::policy::CryptoPolicy;
|
||||
use crate::credential::{Credential, Password};
|
||||
use crate::event::{AuthEvent, AuthResult, CreateEvent, ModifyEvent};
|
||||
|
@ -2107,20 +2107,12 @@ mod tests {
|
|||
PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent,
|
||||
UnixGroupTokenEvent, UnixPasswordChangeEvent, UnixUserAuthEvent, UnixUserTokenEvent,
|
||||
};
|
||||
use crate::idm::server::{IdmServer, IdmServerTransaction};
|
||||
use crate::idm::AuthState;
|
||||
use crate::modify::{Modify, ModifyList};
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthMech, AuthType};
|
||||
|
||||
use crate::idm::server::{IdmServer, IdmServerTransaction};
|
||||
// , IdmServerDelayed;
|
||||
use crate::utils::duration_from_epoch_now;
|
||||
use async_std::task;
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
|
||||
const TEST_PASSWORD: &'static str = "ntaoeuntnaoeuhraohuercahu😍";
|
||||
const TEST_PASSWORD_INC: &'static str = "ntaoentu nkrcgaeunhibwmwmqj;k wqjbkx ";
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::event::SearchEvent;
|
||||
use crate::idm::account::Account;
|
||||
use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerProxyWriteTransaction};
|
||||
use crate::prelude::*;
|
||||
use crate::value::Session;
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
|
||||
// Need to add KID to es256 der for lookups ✅
|
||||
|
||||
// Need to generate the es256 on the account on modifies ✅
|
||||
|
@ -87,14 +87,13 @@ pub struct ServiceAccount {
|
|||
}
|
||||
|
||||
impl ServiceAccount {
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub(crate) fn try_from_entry_rw(
|
||||
value: &Entry<EntrySealed, EntryCommitted>,
|
||||
// qs: &mut QueryServerWriteTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
spanned!("idm::serviceaccount::try_from_entry_rw", {
|
||||
// let groups = Group::try_from_account_entry_rw(value, qs)?;
|
||||
try_from_entry!(value)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn check_api_token_valid(
|
||||
|
@ -354,16 +353,17 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent, GRACE_WINDOW};
|
||||
use crate::idm::server::IdmServerTransaction;
|
||||
// use crate::prelude::*;
|
||||
|
||||
use crate::event::CreateEvent;
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
|
||||
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent, GRACE_WINDOW};
|
||||
// use crate::prelude::*;
|
||||
use crate::event::CreateEvent;
|
||||
use crate::idm::server::IdmServerTransaction;
|
||||
|
||||
const TEST_CURRENT_TIME: u64 = 6000;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
use std::iter;
|
||||
// use crossbeam::channel::Sender;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken};
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::credential::policy::CryptoPolicy;
|
||||
use crate::credential::{softlock::CredSoftLockPolicy, Credential};
|
||||
use crate::credential::softlock::CredSoftLockPolicy;
|
||||
use crate::credential::Credential;
|
||||
use crate::idm::delayed::{DelayedAction, UnixPasswordUpgrade};
|
||||
use crate::modify::{ModifyInvalid, ModifyList};
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
|
||||
use crate::idm::delayed::{DelayedAction, UnixPasswordUpgrade};
|
||||
|
||||
// use crossbeam::channel::Sender;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
|
||||
use std::iter;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct UnixUserAccount {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
//! This contains scheduled tasks/interval tasks that are run inside of the server on a schedule
|
||||
//! as background operations.
|
||||
|
||||
use crate::actors::v1_read::QueryServerReadV1;
|
||||
use crate::actors::v1_write::QueryServerWriteV1;
|
||||
|
||||
use crate::config::OnlineBackup;
|
||||
use crate::constants::PURGE_FREQUENCY;
|
||||
use crate::event::{OnlineBackupEvent, PurgeRecycledEvent, PurgeTombstoneEvent};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use chrono::Utc;
|
||||
use saffron::parse::{CronExpr, English};
|
||||
use saffron::Cron;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use tokio::time::{interval, sleep, Duration};
|
||||
|
||||
use crate::actors::v1_read::QueryServerReadV1;
|
||||
use crate::actors::v1_write::QueryServerWriteV1;
|
||||
use crate::config::OnlineBackup;
|
||||
use crate::constants::PURGE_FREQUENCY;
|
||||
use crate::event::{OnlineBackupEvent, PurgeRecycledEvent, PurgeTombstoneEvent};
|
||||
|
||||
pub struct IntervalActor;
|
||||
|
||||
impl IntervalActor {
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
//! LDAP specific operations handling components. This is where LDAP operations
|
||||
//! are sent to for processing.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::iter;
|
||||
|
||||
use async_std::task;
|
||||
use kanidm_proto::v1::{ApiToken, OperationError, UserAuthToken};
|
||||
use ldap3_proto::simple::*;
|
||||
use regex::Regex;
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::event::SearchEvent;
|
||||
use crate::idm::event::{LdapAuthEvent, LdapTokenAuthEvent};
|
||||
use crate::idm::server::{IdmServer, IdmServerTransaction};
|
||||
use crate::prelude::*;
|
||||
use async_std::task;
|
||||
use kanidm_proto::v1::{ApiToken, OperationError, UserAuthToken};
|
||||
use ldap3_proto::simple::*;
|
||||
use regex::Regex;
|
||||
use std::collections::BTreeSet;
|
||||
use std::iter;
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
// Clippy doesn't like Bind here. But proto needs unboxed ldapmsg,
|
||||
// and ldapboundtoken is moved. Really, it's not too bad, every message here is pretty sucky.
|
||||
|
@ -121,6 +123,7 @@ impl LdapServer {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
async fn do_search(
|
||||
&self,
|
||||
idms: &IdmServer,
|
||||
|
@ -252,7 +255,6 @@ impl LdapServer {
|
|||
|
||||
let ct = duration_from_epoch_now();
|
||||
let idm_read = idms.proxy_read_async().await;
|
||||
spanned!("ldap::do_search<core>", {
|
||||
// Now start the txn - we need it for resolving filter components.
|
||||
|
||||
// join the filter, with ext_filter
|
||||
|
@ -287,20 +289,14 @@ impl LdapServer {
|
|||
// Build the event, with the permissions from effective_session
|
||||
//
|
||||
// ! Remember, searchEvent wraps to ignore hidden for us.
|
||||
let se = spanned!("ldap::do_search<core><prepare_se>", {
|
||||
let ident = idm_read
|
||||
.validate_ldap_session(&uat.effective_session, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
SearchEvent::new_ext_impersonate_uuid(
|
||||
&idm_read.qs_read,
|
||||
ident,
|
||||
&lfilter,
|
||||
k_attrs,
|
||||
)
|
||||
})
|
||||
let se =
|
||||
SearchEvent::new_ext_impersonate_uuid(&idm_read.qs_read, ident, &lfilter, k_attrs)
|
||||
.map_err(|e| {
|
||||
admin_error!("failed to create search event -> {:?}", e);
|
||||
e
|
||||
|
@ -314,7 +310,6 @@ impl LdapServer {
|
|||
// These have already been fully reduced (access controls applied),
|
||||
// so we can just transform the values and open palm slam them into
|
||||
// the result structure.
|
||||
let lres = spanned!("ldap::do_search<core><prepare results>", {
|
||||
let lres: Result<Vec<_>, _> = res
|
||||
.into_iter()
|
||||
.map(|e| {
|
||||
|
@ -324,8 +319,6 @@ impl LdapServer {
|
|||
})
|
||||
.chain(iter::once(Ok(sr.gen_success())))
|
||||
.collect();
|
||||
lres
|
||||
});
|
||||
|
||||
let lres = lres.map_err(|e| {
|
||||
admin_error!("entry resolve failure {:?}", e);
|
||||
|
@ -338,7 +331,6 @@ impl LdapServer {
|
|||
);
|
||||
|
||||
Ok(lres)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,18 +542,19 @@ pub(crate) fn ldap_attr_filter_map(input: &str) -> AttrString {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
// use crate::prelude::*;
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::idm::event::UnixPasswordChangeEvent;
|
||||
use crate::idm::serviceaccount::GenerateApiTokenEvent;
|
||||
use crate::ldap::{LdapServer, LdapSession};
|
||||
use std::str::FromStr;
|
||||
|
||||
use async_std::task;
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope};
|
||||
use ldap3_proto::simple::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::idm::event::UnixPasswordChangeEvent;
|
||||
use crate::idm::serviceaccount::GenerateApiTokenEvent;
|
||||
use crate::ldap::{LdapServer, LdapSession};
|
||||
|
||||
const TEST_PASSWORD: &'static str = "ntaoeuntnaoeuhraohuercahu😍";
|
||||
|
||||
|
|
|
@ -63,39 +63,36 @@ pub mod config;
|
|||
/// A prelude of imports that should be imported by all other Kanidm modules to
|
||||
/// help make imports cleaner.
|
||||
pub mod prelude {
|
||||
pub use crate::utils::duration_from_epoch_now;
|
||||
pub use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
pub use sketching::{
|
||||
admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace,
|
||||
filter_warn, perf_trace, request_error, request_info, request_trace, request_warn,
|
||||
security_access, security_critical, security_error, security_info, tagged_event, EventTag,
|
||||
};
|
||||
pub use smartstring::alias::String as AttrString;
|
||||
pub use url::Url;
|
||||
pub use uuid::Uuid;
|
||||
|
||||
pub use crate::constants::*;
|
||||
pub use crate::filter::{
|
||||
f_and, f_andnot, f_eq, f_id, f_inc, f_lt, f_or, f_pres, f_self, f_spn_name, f_sub,
|
||||
};
|
||||
pub use crate::filter::{Filter, FilterInvalid, FC};
|
||||
pub use crate::modify::{m_pres, m_purge, m_remove};
|
||||
pub use crate::modify::{Modify, ModifyInvalid, ModifyList};
|
||||
|
||||
pub use crate::entry::{
|
||||
Entry, EntryCommitted, EntryInit, EntryInvalid, EntryInvalidCommitted, EntryNew,
|
||||
EntryReduced, EntrySealed, EntrySealedCommitted, EntryTuple, EntryValid,
|
||||
};
|
||||
pub use crate::filter::{
|
||||
f_and, f_andnot, f_eq, f_id, f_inc, f_lt, f_or, f_pres, f_self, f_spn_name, f_sub, Filter,
|
||||
FilterInvalid, FC,
|
||||
};
|
||||
pub use crate::identity::Identity;
|
||||
pub use crate::modify::{m_pres, m_purge, m_remove, Modify, ModifyInvalid, ModifyList};
|
||||
pub use crate::server::{
|
||||
QueryServer, QueryServerReadTransaction, QueryServerTransaction,
|
||||
QueryServerWriteTransaction,
|
||||
};
|
||||
pub use crate::utils::duration_from_epoch_now;
|
||||
pub use crate::value::{IndexType, PartialValue, SyntaxType, Value};
|
||||
pub use crate::valueset::{
|
||||
ValueSet, ValueSetBool, ValueSetCid, ValueSetIndex, ValueSetIutf8, ValueSetRefer,
|
||||
ValueSetSecret, ValueSetSpn, ValueSetSyntax, ValueSetT, ValueSetUint32, ValueSetUtf8,
|
||||
ValueSetUuid,
|
||||
};
|
||||
pub use sketching::{
|
||||
admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace,
|
||||
filter_warn, perf_trace, request_error, request_info, request_trace, request_warn,
|
||||
security_access, security_critical, security_error, security_info, spanned, tagged_event,
|
||||
EventTag,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -19,9 +19,10 @@ macro_rules! setup_test {
|
|||
(
|
||||
$preload_entries:expr
|
||||
) => {{
|
||||
use crate::utils::duration_from_epoch_now;
|
||||
use async_std::task;
|
||||
|
||||
use crate::utils::duration_from_epoch_now;
|
||||
|
||||
let _ = sketching::test_init();
|
||||
|
||||
// Create an in memory BE
|
||||
|
@ -105,10 +106,11 @@ macro_rules! run_test {
|
|||
#[cfg(test)]
|
||||
macro_rules! entry_str_to_account {
|
||||
($entry_str:expr) => {{
|
||||
use std::iter::once;
|
||||
|
||||
use crate::entry::{Entry, EntryInvalid, EntryNew};
|
||||
use crate::idm::account::Account;
|
||||
use crate::value::Value;
|
||||
use std::iter::once;
|
||||
|
||||
let mut e: Entry<EntryInvalid, EntryNew> =
|
||||
unsafe { Entry::unsafe_from_entry_str($entry_str).into_invalid_new() };
|
||||
|
@ -195,7 +197,6 @@ macro_rules! run_create_test {
|
|||
use crate::schema::Schema;
|
||||
use crate::utils::duration_from_epoch_now;
|
||||
|
||||
spanned!("plugins::macros::run_create_test", {
|
||||
let qs = setup_test!($preload_entries);
|
||||
|
||||
let ce = match $internal {
|
||||
|
@ -225,7 +226,6 @@ macro_rules! run_create_test {
|
|||
let ver = qs.verify();
|
||||
trace!("verification -> {:?}", ver);
|
||||
assert!(ver.len() == 0);
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -246,14 +246,11 @@ macro_rules! run_modify_test {
|
|||
use crate::prelude::*;
|
||||
use crate::schema::Schema;
|
||||
|
||||
spanned!("plugins::macros::run_modify_test", {
|
||||
let qs = setup_test!($preload_entries);
|
||||
|
||||
{
|
||||
let qs_write = qs.write(duration_from_epoch_now());
|
||||
spanned!("plugins::macros::run_modify_test -> pre_test hook", {
|
||||
$pre_hook(&qs_write)
|
||||
});
|
||||
$pre_hook(&qs_write);
|
||||
qs_write.commit().expect("commit failure!");
|
||||
}
|
||||
|
||||
|
@ -266,12 +263,8 @@ macro_rules! run_modify_test {
|
|||
|
||||
{
|
||||
let qs_write = qs.write(duration_from_epoch_now());
|
||||
let r = spanned!("plugins::macros::run_modify_test -> main_test", {
|
||||
qs_write.modify(&me)
|
||||
});
|
||||
spanned!("plugins::macros::run_modify_test -> post_test check", {
|
||||
$check(&qs_write)
|
||||
});
|
||||
let r = qs_write.modify(&me);
|
||||
$check(&qs_write);
|
||||
trace!("test result: {:?}", r);
|
||||
assert!(r == $expect);
|
||||
match r {
|
||||
|
@ -288,7 +281,6 @@ macro_rules! run_modify_test {
|
|||
let ver = qs.verify();
|
||||
trace!("verification -> {:?}", ver);
|
||||
assert!(ver.len() == 0);
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -308,7 +300,6 @@ macro_rules! run_delete_test {
|
|||
use crate::schema::Schema;
|
||||
use crate::utils::duration_from_epoch_now;
|
||||
|
||||
spanned!("plugins::macros::run_delete_test", {
|
||||
let qs = setup_test!($preload_entries);
|
||||
|
||||
let de = match $internal {
|
||||
|
@ -338,7 +329,6 @@ macro_rules! run_delete_test {
|
|||
let ver = qs.verify();
|
||||
trace!("verification -> {:?}", ver);
|
||||
assert!(ver.len() == 0);
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
//! express the series of Modifications that should be applied. These are expressed
|
||||
//! as "states" on what attribute-values should appear as within the `Entry`
|
||||
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use kanidm_proto::v1::Modify as ProtoModify;
|
||||
use kanidm_proto::v1::ModifyList as ProtoModifyList;
|
||||
|
||||
use crate::schema::SchemaTransaction;
|
||||
use crate::value::{PartialValue, Value};
|
||||
use kanidm_proto::v1::{OperationError, SchemaError};
|
||||
use std::slice;
|
||||
|
||||
use kanidm_proto::v1::{
|
||||
Entry as ProtoEntry, Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError,
|
||||
SchemaError,
|
||||
};
|
||||
// Should this be std?
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use std::slice;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use crate::value::{PartialValue, Value};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ModifyValid;
|
||||
|
@ -69,8 +69,8 @@ pub struct ModifyList<VALID> {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a ModifyList<ModifyValid> {
|
||||
type Item = &'a Modify;
|
||||
type IntoIter = slice::Iter<'a, Modify>;
|
||||
type Item = &'a Modify;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.mods.iter()
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
// both change approaches.
|
||||
//
|
||||
//
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
use tracing::trace;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct AttrUnique;
|
||||
|
||||
|
@ -192,9 +193,10 @@ impl Plugin for AttrUnique {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
// Test entry in db, and same name, reject.
|
||||
#[test]
|
||||
fn test_pre_create_name_unique() {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use crate::plugins::Plugin;
|
||||
use hashbrown::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
use std::iter::once;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::modify::Modify;
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
|
||||
lazy_static! {
|
||||
static ref CLASS_OBJECT: Value = Value::new_class("object");
|
||||
|
@ -43,15 +44,9 @@ impl Plugin for Base {
|
|||
// debug!("Entering base pre_create_transform");
|
||||
// For each candidate
|
||||
for entry in cand.iter_mut() {
|
||||
trace!("Base check on entry: {:?}", entry);
|
||||
|
||||
// First, ensure we have the 'object', class in the class set.
|
||||
entry.add_ava("class", CLASS_OBJECT.clone());
|
||||
|
||||
trace!("Object should now be in entry: {:?}", entry);
|
||||
|
||||
// If they have a name, but no principal name, derive it.
|
||||
|
||||
// if they don't have uuid, create it.
|
||||
match entry.get_ava_set("uuid").map(|s| s.len()) {
|
||||
None => {
|
||||
|
@ -85,7 +80,6 @@ impl Plugin for Base {
|
|||
let uuid_ref: Uuid = entry
|
||||
.get_ava_single_uuid("uuid")
|
||||
.ok_or_else(|| OperationError::InvalidAttribute("uuid".to_string()))?;
|
||||
trace!("Entry valid UUID: {:?}", entry);
|
||||
if !cand_uuid.insert(uuid_ref) {
|
||||
trace!("uuid duplicate found in create set! {:?}", uuid_ref);
|
||||
return Err(OperationError::Plugin(PluginError::Base(
|
||||
|
@ -224,9 +218,10 @@ impl Plugin for Base {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
const JSON_ADMIN_ALLOW_ALL: &'static str = r#"{
|
||||
"attrs": {
|
||||
"class": [
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
// The primary point of this is to generate a unique domain UUID on startup
|
||||
// which is importart for management of the replication topo and trust
|
||||
// relationships.
|
||||
use crate::plugins::Plugin;
|
||||
use std::iter::once;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::prelude::*;
|
||||
use compact_jwt::JwsSigner;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use std::iter::once;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
|
||||
lazy_static! {
|
||||
static ref PVCLASS_DOMAIN_INFO: PartialValue = PartialValue::new_class("domain_info");
|
||||
static ref PVUUID_DOMAIN_INFO: PartialValue = PartialValue::new_uuid(*UUID_DOMAIN_INFO);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::filter::FilterInvalid;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
lazy_static! {
|
||||
static ref CLASS_DYNGROUP: PartialValue = PartialValue::new_class("dyngroup");
|
||||
|
@ -361,9 +363,10 @@ impl DynGroup {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
const UUID_TEST_GROUP: Uuid = uuid::uuid!("7bfd9931-06c2-4608-8a46-78719bb746fe");
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// A plugin that generates gid numbers on types that require them for posix
|
||||
// support.
|
||||
|
||||
use std::iter::once;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use crate::utils::uuid_to_gid_u32;
|
||||
use std::iter::once;
|
||||
|
||||
/// Systemd dynamic units allocate between 61184–65519, most distros allocate
|
||||
/// system uids from 0 - 1000, and many others give user ids between 1000 to
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use compact_jwt::JwsSigner;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use crate::utils::password_from_random;
|
||||
use compact_jwt::JwsSigner;
|
||||
|
||||
lazy_static! {
|
||||
static ref CLASS_OAUTH2_BASIC: PartialValue =
|
||||
|
|
|
@ -10,16 +10,17 @@
|
|||
// As a result, we first need to run refint to clean up all dangling references, then memberof
|
||||
// fixes the graph of memberships
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntrySealed, EntryTuple};
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use crate::value::{PartialValue, Value};
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
lazy_static! {
|
||||
static ref CLASS_GROUP: PartialValue = PartialValue::new_class("group");
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
//! helps to ensure that data is always in specific known states within the
|
||||
//! `QueryServer`
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use std::sync::Arc;
|
||||
use tracing::trace_span;
|
||||
|
||||
mod attrunique;
|
||||
mod base;
|
||||
|
@ -118,12 +119,12 @@ macro_rules! run_verify_plugin {
|
|||
}
|
||||
|
||||
impl Plugins {
|
||||
#[instrument(level = "debug", name = "plugins::run_pre_create_transform", skip_all)]
|
||||
pub fn run_pre_create_transform(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
cand: &mut Vec<Entry<EntryInvalid, EntryNew>>,
|
||||
ce: &CreateEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_pre_create_transform", {
|
||||
base::Base::pre_create_transform(qs, cand, ce)
|
||||
.and_then(|_| password_import::PasswordImport::pre_create_transform(qs, cand, ce))
|
||||
.and_then(|_| jwskeygen::JwsKeygen::pre_create_transform(qs, cand, ce))
|
||||
|
@ -132,36 +133,33 @@ impl Plugins {
|
|||
.and_then(|_| spn::Spn::pre_create_transform(qs, cand, ce))
|
||||
// Should always be last
|
||||
.and_then(|_| attrunique::AttrUnique::pre_create_transform(qs, cand, ce))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_pre_create", skip_all)]
|
||||
pub fn run_pre_create(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
cand: &[Entry<EntrySealed, EntryNew>],
|
||||
ce: &CreateEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_pre_create", {
|
||||
protected::Protected::pre_create(qs, cand, ce)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_post_create", skip_all)]
|
||||
pub fn run_post_create(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
cand: &[Entry<EntrySealed, EntryCommitted>],
|
||||
ce: &CreateEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_post_create", {
|
||||
refint::ReferentialIntegrity::post_create(qs, cand, ce)
|
||||
.and_then(|_| memberof::MemberOf::post_create(qs, cand, ce))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_pre_modify", skip_all)]
|
||||
pub fn run_pre_modify(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>,
|
||||
me: &ModifyEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_pre_modify", {
|
||||
protected::Protected::pre_modify(qs, cand, me)
|
||||
.and_then(|_| base::Base::pre_modify(qs, cand, me))
|
||||
.and_then(|_| password_import::PasswordImport::pre_modify(qs, cand, me))
|
||||
|
@ -171,55 +169,49 @@ impl Plugins {
|
|||
.and_then(|_| spn::Spn::pre_modify(qs, cand, me))
|
||||
// attr unique should always be last
|
||||
.and_then(|_| attrunique::AttrUnique::pre_modify(qs, cand, me))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_post_modify", skip_all)]
|
||||
pub fn run_post_modify(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
pre_cand: &[Arc<Entry<EntrySealed, EntryCommitted>>],
|
||||
cand: &[Entry<EntrySealed, EntryCommitted>],
|
||||
me: &ModifyEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_post_modify", {
|
||||
refint::ReferentialIntegrity::post_modify(qs, pre_cand, cand, me)
|
||||
.and_then(|_| spn::Spn::post_modify(qs, pre_cand, cand, me))
|
||||
.and_then(|_| memberof::MemberOf::post_modify(qs, pre_cand, cand, me))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_pre_delete", skip_all)]
|
||||
pub fn run_pre_delete(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>,
|
||||
de: &DeleteEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_pre_delete", {
|
||||
protected::Protected::pre_delete(qs, cand, de)
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_post_delete", skip_all)]
|
||||
pub fn run_post_delete(
|
||||
qs: &QueryServerWriteTransaction,
|
||||
cand: &[Entry<EntrySealed, EntryCommitted>],
|
||||
de: &DeleteEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
spanned!("plugins::run_post_delete", {
|
||||
refint::ReferentialIntegrity::post_delete(qs, cand, de)
|
||||
.and_then(|_| memberof::MemberOf::post_delete(qs, cand, de))
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "plugins::run_verify", skip_all)]
|
||||
pub fn run_verify(
|
||||
qs: &QueryServerReadTransaction,
|
||||
results: &mut Vec<Result<(), ConsistencyError>>,
|
||||
) {
|
||||
let _entered = trace_span!("plugins::run_verify").entered();
|
||||
spanned!("plugins::run_verify", {
|
||||
run_verify_plugin!(qs, results, base::Base);
|
||||
run_verify_plugin!(qs, results, attrunique::AttrUnique);
|
||||
run_verify_plugin!(qs, results, refint::ReferentialIntegrity);
|
||||
run_verify_plugin!(qs, results, dyngroup::DynGroup);
|
||||
run_verify_plugin!(qs, results, memberof::MemberOf);
|
||||
run_verify_plugin!(qs, results, spn::Spn);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// Transform password import requests into proper kanidm credentials.
|
||||
use std::convert::TryFrom;
|
||||
use std::iter::once;
|
||||
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
use crate::credential::{Credential, Password};
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
use std::convert::TryFrom;
|
||||
use std::iter::once;
|
||||
|
||||
pub struct PasswordImport {}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// System protected objects. Items matching specific requirements
|
||||
// may only have certain modifications performed.
|
||||
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::modify::Modify;
|
||||
use hashbrown::HashSet;
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct Protected {}
|
||||
|
||||
|
|
|
@ -9,19 +9,19 @@
|
|||
// when that is written, as they *both* manipulate and alter entry reference
|
||||
// data, so we should be careful not to step on each other.
|
||||
|
||||
use hashbrown::HashSet as Set;
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use hashbrown::HashSet as Set;
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::filter::f_eq;
|
||||
use crate::modify::Modify;
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
use std::sync::Arc;
|
||||
use tracing::trace;
|
||||
|
||||
// NOTE: This *must* be after base.rs!!!
|
||||
|
||||
|
@ -265,9 +265,10 @@ impl Plugin for ReferentialIntegrity {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
// The create references a uuid that doesn't exist - reject
|
||||
#[test]
|
||||
fn test_create_uuid_reference_not_exist() {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
// Generate and manage spn's for all entries in the domain. Also deals with
|
||||
// the infrequent - but possible - case where a domain is renamed.
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use std::iter::once;
|
||||
use std::sync::Arc;
|
||||
|
||||
// use crate::value::{PartialValue, Value};
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use crate::constants::UUID_DOMAIN_INFO;
|
||||
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
use crate::prelude::*;
|
||||
use crate::value::PartialValue;
|
||||
// use crate::value::{PartialValue, Value};
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use std::iter::once;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Spn {}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use kanidm_proto::v1::OperationError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -73,11 +74,13 @@ impl Cid {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::repl::cid::Cid;
|
||||
use std::cmp::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::repl::cid::Cid;
|
||||
|
||||
#[test]
|
||||
fn test_cid_ordering() {
|
||||
// Check diff ts
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
use super::cid::Cid;
|
||||
use crate::prelude::*;
|
||||
use crate::valueset;
|
||||
use kanidm_proto::v1::ConsistencyError;
|
||||
|
||||
use crate::entry::{compare_attrs, Eattrs};
|
||||
use crate::schema::SchemaTransaction;
|
||||
|
||||
use std::collections::btree_map::Keys;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::Bound;
|
||||
use std::ops::Bound::*;
|
||||
|
||||
use kanidm_proto::v1::ConsistencyError;
|
||||
|
||||
use super::cid::Cid;
|
||||
use crate::entry::{compare_attrs, Eattrs};
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
use crate::valueset;
|
||||
|
||||
lazy_static! {
|
||||
static ref PVCLASS_TOMBSTONE: PartialValue = PartialValue::new_class("tombstone");
|
||||
static ref PVCLASS_RECYCLED: PartialValue = PartialValue::new_class("recycled");
|
||||
|
@ -518,12 +517,13 @@ impl EntryChangelog {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::entry::Eattrs;
|
||||
// use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
use crate::repl::entry::{Change, EntryChangelog, State, Transition};
|
||||
use crate::schema::{Schema, SchemaTransaction};
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn test_entrychangelog_basic() {
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn};
|
||||
use idlset::v2::IDLBitRange;
|
||||
use kanidm_proto::v1::ConsistencyError;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::ops::Bound::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn};
|
||||
use idlset::v2::IDLBitRange;
|
||||
use kanidm_proto::v1::ConsistencyError;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
|
||||
pub struct ReplicationUpdateVector {
|
||||
// This sorts by time. Should we look up by IDL or by UUID?
|
||||
// I think IDL, because when we need to actually do the look ups we'll need
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue