Rework deps (#1079)

This commit is contained in:
Firstyear 2022-10-01 16:08:51 +10:00 committed by GitHub
parent 8e0238ab97
commit 821b2c05c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
181 changed files with 6355 additions and 7591 deletions

11
.rustfmt.toml Normal file
View 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
View file

@ -82,6 +82,21 @@ dependencies = [
"memchr", "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]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.5" version = "0.1.5"
@ -186,6 +201,7 @@ version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695" checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695"
dependencies = [ dependencies = [
"brotli",
"flate2", "flate2",
"futures-core", "futures-core",
"futures-io", "futures-io",
@ -578,6 +594,27 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" 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]] [[package]]
name = "bstr" name = "bstr"
version = "0.2.17" version = "0.2.17"
@ -602,6 +639,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "bytemuck"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@ -753,6 +796,12 @@ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "compact_jwt" name = "compact_jwt"
version = "0.2.8" version = "0.2.8"
@ -850,9 +899,9 @@ dependencies = [
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.16.0" version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917"
dependencies = [ dependencies = [
"percent-encoding", "percent-encoding",
"time 0.3.14", "time 0.3.14",
@ -865,7 +914,7 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd"
dependencies = [ dependencies = [
"cookie 0.16.0", "cookie 0.16.1",
"idna 0.2.3", "idna 0.2.3",
"log", "log",
"publicsuffix", "publicsuffix",
@ -1991,6 +2040,19 @@ dependencies = [
"want", "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]] [[package]]
name = "hyper-tls" name = "hyper-tls"
version = "0.5.0" version = "0.5.0"
@ -2061,6 +2123,20 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" 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]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.1" version = "1.9.1"
@ -2174,7 +2250,7 @@ dependencies = [
"rusqlite", "rusqlite",
"saffron", "saffron",
"serde", "serde",
"serde_cbor", "serde_cbor_2",
"serde_json", "serde_json",
"sketching", "sketching",
"smartstring", "smartstring",
@ -2664,6 +2740,28 @@ dependencies = [
"num-traits", "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]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -2724,6 +2822,7 @@ dependencies = [
"getrandom 0.2.7", "getrandom 0.2.7",
"http", "http",
"rand 0.8.5", "rand 0.8.5",
"reqwest",
"serde", "serde",
"serde_json", "serde_json",
"serde_path_to_error", "serde_path_to_error",
@ -2773,9 +2872,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.41" version = "0.10.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cfg-if 1.0.0", "cfg-if 1.0.0",
@ -2805,9 +2904,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.75" version = "0.9.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cc", "cc",
@ -2919,6 +3018,24 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 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]] [[package]]
name = "phonenumber" name = "phonenumber"
version = "0.3.1+8.12.9" version = "0.3.1+8.12.9"
@ -3085,9 +3202,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.43" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -3124,6 +3241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f"
dependencies = [ dependencies = [
"checked_int_cast", "checked_int_cast",
"image",
] ]
[[package]] [[package]]
@ -3341,7 +3459,7 @@ checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc"
dependencies = [ dependencies = [
"base64 0.13.0", "base64 0.13.0",
"bytes", "bytes",
"cookie 0.16.0", "cookie 0.16.1",
"cookie_store", "cookie_store",
"encoding_rs", "encoding_rs",
"futures-core", "futures-core",
@ -3350,6 +3468,7 @@ dependencies = [
"http", "http",
"http-body", "http-body",
"hyper", "hyper",
"hyper-rustls",
"hyper-tls", "hyper-tls",
"ipnet", "ipnet",
"js-sys", "js-sys",
@ -3360,19 +3479,38 @@ dependencies = [
"percent-encoding", "percent-encoding",
"pin-project-lite 0.2.9", "pin-project-lite 0.2.9",
"proc-macro-hack", "proc-macro-hack",
"rustls",
"rustls-pemfile",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
"tokio-rustls",
"tower-service", "tower-service",
"url", "url",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-futures", "wasm-bindgen-futures",
"web-sys", "web-sys",
"webpki-roots",
"winreg", "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]] [[package]]
name = "route-recognizer" name = "route-recognizer"
version = "0.2.0" version = "0.2.0"
@ -3443,6 +3581,27 @@ dependencies = [
"nom 7.1.1", "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]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.11" version = "1.0.11"
@ -3511,7 +3670,6 @@ version = "1.1.0-alpha.9"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-trait", "async-trait",
"base64 0.13.0",
"compact_jwt", "compact_jwt",
"futures", "futures",
"futures-util", "futures-util",
@ -3541,6 +3699,16 @@ dependencies = [
"webauthn-authenticator-rs", "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]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.7.0" version = "2.7.0"
@ -3800,9 +3968,15 @@ dependencies = [
"event-listener", "event-listener",
] ]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]] [[package]]
name = "sketching" name = "sketching"
version = "0.1.0" version = "1.1.0-alpha.9"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"num_enum", "num_enum",
@ -3861,6 +4035,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]] [[package]]
name = "sptr" name = "sptr"
version = "0.3.2" version = "0.3.2"
@ -3965,9 +4145,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.100" version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -4027,18 +4207,18 @@ checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -4086,6 +4266,7 @@ dependencies = [
"async-compression", "async-compression",
"futures-lite", "futures-lite",
"http-types", "http-types",
"phf",
"regex", "regex",
"tide", "tide",
] ]
@ -4273,6 +4454,17 @@ dependencies = [
"tokio", "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]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.4" version = "0.7.4"
@ -4441,6 +4633,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "url" name = "url"
version = "2.3.1" version = "2.3.1"
@ -4774,6 +4972,25 @@ dependencies = [
"web-sys", "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]] [[package]]
name = "wepoll-ffi" name = "wepoll-ffi"
version = "0.1.2" version = "0.1.2"

View file

@ -17,20 +17,131 @@ members = [
"kanidmd/score", "kanidmd/score",
"orca", "orca",
"profiles", "profiles",
"sketching", "sketching"
] ]
exclude = [ exclude = [
"kanidm_unix_int/pam_tester" "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] [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" } # compact_jwt = { path = "../compact_jwt" }
concread = "^0.4.0"
# concread = { path = "../concread" } # 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" } # 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-authenticator-rs = "0.4.7"
webauthn-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 = { path = "../webauthn-rs/webauthn-rs" }
# webauthn-rs-core = { path = "../webauthn-rs/webauthn-rs-core" } # webauthn-rs-core = { path = "../webauthn-rs/webauthn-rs-core" }
# webauthn-rs-proto = { path = "../webauthn-rs/webauthn-rs-proto" } # 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 # enshrinken the WASMs
[profile.release.package.kanidmd_web_ui] [profile.release.package.kanidmd_web_ui]

View file

@ -1,25 +1,26 @@
[package] [package]
name = "kanidm_client" 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" description = "Kanidm Client Library"
documentation = "https://docs.rs/kanidm_client/latest/kanidm_client/" 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] [dependencies]
tracing = "^0.1.35" tracing.workspace = true
reqwest = { version = "^0.11.11", features=["cookies", "json", "native-tls"] } reqwest = { workspace = true, features=["cookies", "json", "native-tls"] }
kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" } kanidm_proto.workspace = true
serde = { version = "^1.0.142", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = "^1.0.83" serde_json.workspace = true
time = { version = "=0.2.27", features = ["serde", "std"] } time = { workspace = true, features = ["serde", "std"] }
tokio = { version = "^1.21.1", features = ["rt", "net", "time", "macros", "sync", "signal"] } tokio = { workspace = true, features = ["rt", "net", "time", "macros", "sync", "signal"] }
toml = "^0.5.9" toml.workspace = true
uuid = { version = "^1.1.2", features = ["serde", "v4"] } uuid = { workspace = true, features = ["serde", "v4"] }
url = { version = "^2.3.1", features = ["serde"] } url = { workspace = true, features = ["serde"] }
webauthn-rs-proto = { workspace = true, features = ["wasm"] } webauthn-rs-proto = { workspace = true, features = ["wasm"] }

View file

@ -13,32 +13,26 @@
#[macro_use] #[macro_use]
extern crate tracing; extern crate tracing;
use reqwest::header::CONTENT_TYPE; use std::collections::{BTreeMap, BTreeSet as Set};
use serde::de::DeserializeOwned;
use serde::Deserialize;
use serde::Serialize;
use serde_json::error::Error as SerdeJsonError;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::fs::File; use std::fs::File;
#[cfg(target_family = "unix")] // not needed for windows builds #[cfg(target_family = "unix")] // not needed for windows builds
use std::fs::{metadata, Metadata}; use std::fs::{metadata, Metadata};
use std::io::ErrorKind; use std::io::{ErrorKind, Read};
use std::io::Read;
#[cfg(target_family = "unix")] // not needed for windows builds #[cfg(target_family = "unix")] // not needed for windows builds
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::collections::BTreeMap;
use std::collections::BTreeSet as Set;
use std::path::Path; use std::path::Path;
use std::time::Duration; 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 tokio::sync::RwLock;
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
pub use reqwest::StatusCode;
use kanidm_proto::v1::*;
use webauthn_rs_proto::{ use webauthn_rs_proto::{
PublicKeyCredential, RegisterPublicKeyCredential, RequestChallengeResponse, PublicKeyCredential, RegisterPublicKeyCredential, RequestChallengeResponse,
}; };
@ -1767,6 +1761,7 @@ impl KanidmClient {
self.perform_patch_request(format!("/v1/oauth2/{}", id).as_str(), update_oauth2_rs) self.perform_patch_request(format!("/v1/oauth2/{}", id).as_str(), update_oauth2_rs)
.await .await
} }
pub async fn idm_oauth2_rs_prefer_spn_username(&self, id: &str) -> Result<(), ClientError> { pub async fn idm_oauth2_rs_prefer_spn_username(&self, id: &str) -> Result<(), ClientError> {
let mut update_oauth2_rs = Entry { let mut update_oauth2_rs = Entry {
attrs: BTreeMap::new(), attrs: BTreeMap::new(),

View file

@ -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 std::collections::BTreeMap;
use kanidm_proto::v1::{AccountUnixExtend, CredentialStatus, Entry, SingleStringRequest};
use crate::{ClientError, KanidmClient};
impl KanidmClient { impl KanidmClient {
pub async fn idm_person_account_list(&self) -> Result<Vec<Entry>, ClientError> { pub async fn idm_person_account_list(&self) -> Result<Vec<Entry>, ClientError> {
self.perform_get_request("/v1/person").await self.perform_get_request("/v1/person").await

View file

@ -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 std::collections::BTreeMap;
use kanidm_proto::v1::{AccountUnixExtend, ApiToken, ApiTokenGenerate, CredentialStatus, Entry};
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;
use crate::{ClientError, KanidmClient};
impl KanidmClient { impl KanidmClient {
pub async fn idm_service_account_list(&self) -> Result<Vec<Entry>, ClientError> { pub async fn idm_service_account_list(&self) -> Result<Vec<Entry>, ClientError> {
self.perform_get_request("/v1/service_account").await self.perform_get_request("/v1/service_account").await

View file

@ -1,30 +1,30 @@
[package] [package]
name = "kanidm_proto" 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" description = "Kanidm Protocol Bindings for serde"
documentation = "https://docs.rs/kanidm_proto/latest/kanidm_proto/" 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] [features]
wasm = ["webauthn-rs-proto/wasm"] wasm = ["webauthn-rs-proto/wasm"]
[dependencies] [dependencies]
base32 = "^0.4.0" base32.workspace = true
base64urlsafedata = "0.1.0" base64urlsafedata.workspace = true
serde = { version = "^1.0.142", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = "^1.0.83" serde_json.workspace = true
# Can not upgrade due to breaking timezone apis. time = { workspace = true, features = ["serde", "std"] }
time = { version = "=0.2.27", features = ["serde", "std"] } url = { workspace = true, features = ["serde"] }
url = { version = "^2.3.1", features = ["serde"] } urlencoding.workspace = true
urlencoding = "2.1.2" uuid = { workspace = true, features = ["serde"] }
uuid = { version = "^1.1.2", features = ["serde"] }
webauthn-rs-proto.workspace = true webauthn-rs-proto.workspace = true
[target.'cfg(not(target_family = "wasm"))'.dependencies] [target.'cfg(not(target_family = "wasm"))'.dependencies]
last-git-commit = "0.2.0" last-git-commit.workspace = true

View file

@ -1,9 +1,10 @@
// User-facing output things // User-facing output things
use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use serde::{Deserialize, Serialize};
/// This is used in user-facing CLIs to set the formatting for output, /// This is used in user-facing CLIs to set the formatting for output,
/// and defaults to text. /// and defaults to text.
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
@ -21,6 +22,7 @@ impl Default for ConsoleOutputMode {
impl FromStr for ConsoleOutputMode { impl FromStr for ConsoleOutputMode {
type Err = &'static str; type Err = &'static str;
/// This can be safely unwrap'd because it'll always return a default of text /// This can be safely unwrap'd because it'll always return a default of text
/// ``` /// ```
/// use kanidm_proto::messages::ConsoleOutputMode; /// use kanidm_proto::messages::ConsoleOutputMode;
@ -141,7 +143,6 @@ impl Default for AccountChangeMessage {
/// msg.output_mode = ConsoleOutputMode::JSON; /// msg.output_mode = ConsoleOutputMode::JSON;
/// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\",\"src_user\":\"Kani\",\"dest_user\":\"Krabby\"}"; /// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\",\"src_user\":\"Kani\",\"dest_user\":\"Krabby\"}";
/// assert_eq!(format!("{}", msg), expected_result); /// assert_eq!(format!("{}", msg), expected_result);
///
/// ``` /// ```
impl fmt::Display for AccountChangeMessage { impl fmt::Display for AccountChangeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -149,7 +150,7 @@ impl fmt::Display for AccountChangeMessage {
ConsoleOutputMode::JSON => write!( ConsoleOutputMode::JSON => write!(
f, 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!( ConsoleOutputMode::Text => write!(
f, f,
@ -182,20 +183,20 @@ impl Default for BasicMessage {
/// This outputs in either JSON or Text depending on the output_mode setting /// This outputs in either JSON or Text depending on the output_mode setting
/// ``` /// ```
/// use std::fmt::format;
/// use kanidm_proto::messages::*; /// use kanidm_proto::messages::*;
/// use std::fmt::format;
/// let mut msg = BasicMessage::default(); /// let mut msg = BasicMessage::default();
/// msg.action=String::from("cake_eating"); /// msg.action = String::from("cake_eating");
/// msg.result=String::from("It was amazing"); /// msg.result = String::from("It was amazing");
/// assert_eq!(msg.status, MessageStatus::Success); /// assert_eq!(msg.status, MessageStatus::Success);
/// ///
/// let expected_result = "success - cake_eating: It was amazing"; /// let expected_result = "success - cake_eating: It was amazing";
/// assert_eq!(format!("{}", msg), expected_result); /// assert_eq!(format!("{}", msg), expected_result);
/// ///
/// msg.output_mode = ConsoleOutputMode::JSON; /// 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); /// assert_eq!(format!("{}", msg), expected_result);
///
/// ``` /// ```
impl fmt::Display for BasicMessage { impl fmt::Display for BasicMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -203,7 +204,7 @@ impl fmt::Display for BasicMessage {
ConsoleOutputMode::JSON => write!( ConsoleOutputMode::JSON => write!(
f, 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 => { ConsoleOutputMode::Text => {
write!(f, "{} - {}: {}", self.status, self.action, self.result,) write!(f, "{} - {}: {}", self.status, self.action, self.result,)

View file

@ -1,6 +1,7 @@
use std::collections::BTreeMap;
use base64urlsafedata::Base64UrlSafeData; use base64urlsafedata::Base64UrlSafeData;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use url::Url; use url::Url;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]

View file

@ -1,8 +1,8 @@
use serde::{Deserialize, Serialize};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::fmt; use std::fmt;
use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use webauthn_rs_proto::{ use webauthn_rs_proto::{
CreationChallengeResponse, PublicKeyCredential, RegisterPublicKeyCredential, CreationChallengeResponse, PublicKeyCredential, RegisterPublicKeyCredential,
@ -1068,8 +1068,7 @@ impl SingleStringRequest {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::v1::Filter as ProtoFilter; use crate::v1::{Filter as ProtoFilter, TotpAlgo, TotpSecret};
use crate::v1::{TotpAlgo, TotpSecret};
#[test] #[test]
fn test_protofilter_simple() { fn test_protofilter_simple() {

View file

@ -1,15 +1,16 @@
[package] [package]
name = "kanidm_tools" 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" default-run = "kanidm"
license = "MPL-2.0"
description = "Kanidm Client Tools" description = "Kanidm Client Tools"
documentation = "https://docs.rs/kanidm_tools/latest/kanidm_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] [lib]
name = "kanidm_cli" name = "kanidm_cli"
@ -29,28 +30,28 @@ name = "kanidm_badlist_preprocess"
path = "src/badlist_preprocess.rs" path = "src/badlist_preprocess.rs"
[dependencies] [dependencies]
clap = { version = "^3.2", features = ["derive", "env"] } clap = { workspace = true, features = ["derive", "env"] }
compact_jwt = "^0.2.3" compact_jwt.workspace = true
dialoguer = "^0.10.1" dialoguer.workspace = true
libc = "^0.2.127" libc.workspace = true
kanidm_client = { path = "../kanidm_client", version = "1.1.0-alpha.8" } kanidm_client.workspace = true
kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" } kanidm_proto.workspace = true
qrcode = { version = "^0.12.0", default-features = false } qrcode = { workspace = true, default-features = false }
rayon = "^1.5.3" rayon.workspace = true
rpassword = "^7.0.0" rpassword.workspace = true
serde = { version = "^1.0.142", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = "^1.0.83" serde_json.workspace = true
shellexpand = "^2.1.2" shellexpand.workspace = true
time = { version = "=0.2.27", features = ["serde", "std"] } time = { workspace = true, features = ["serde", "std"] }
tracing = "^0.1.35" tracing.workspace = true
tracing-subscriber = { version = "^0.3.14", features = ["env-filter", "fmt"] } tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
tokio = { version = "^1.21.1", features = ["rt", "macros"] } tokio = { workspace = true, features = ["rt", "macros"] }
url = { version = "^2.3.1", features = ["serde"] } url = { workspace = true, features = ["serde"] }
uuid = "^1.1.2" uuid.workspace = true
webauthn-authenticator-rs = { workspace = true, features = ["u2fhid"] } webauthn-authenticator-rs = { workspace = true, features = ["u2fhid"] }
zxcvbn = "^2.2.1" zxcvbn.workspace = true
[build-dependencies] [build-dependencies]
clap = { version = "^3.2", features = ["derive"] } clap = { workspace = true, features = ["derive"] }
clap_complete = { version = "^3.2.5"} clap_complete.workspace = true
uuid = "^1.1.2" uuid.workspace = true

View file

@ -2,10 +2,10 @@
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use uuid::Uuid;
use clap::{CommandFactory, Parser}; use clap::{CommandFactory, Parser};
use clap_complete::{generate_to, Shell}; use clap_complete::{generate_to, Shell};
use uuid::Uuid;
include!("src/opt/ssh_authorizedkeys.rs"); include!("src/opt/ssh_authorizedkeys.rs");
include!("src/opt/badlist_preprocess.rs"); include!("src/opt/badlist_preprocess.rs");

View file

@ -14,9 +14,8 @@ use std::io::BufWriter;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use kanidm_proto::v1::Modify;
use clap::Parser; use clap::Parser;
use kanidm_proto::v1::Modify;
use rayon::prelude::*; use rayon::prelude::*;
use tracing::{debug, error, info}; use tracing::{debug, error, info};

View file

@ -1,11 +1,14 @@
use crate::session::read_tokens; use std::str::FromStr;
use crate::CommonOpt;
use compact_jwt::{Jws, JwsUnverified}; use compact_jwt::{Jws, JwsUnverified};
use dialoguer::{theme::ColorfulTheme, Select}; use dialoguer::theme::ColorfulTheme;
use dialoguer::Select;
use kanidm_client::{KanidmClient, KanidmClientBuilder}; use kanidm_client::{KanidmClient, KanidmClientBuilder};
use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME}; use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME};
use kanidm_proto::v1::UserAuthToken; use kanidm_proto::v1::UserAuthToken;
use std::str::FromStr;
use crate::session::read_tokens;
use crate::CommonOpt;
impl CommonOpt { impl CommonOpt {
pub fn to_unauth_client(&self) -> KanidmClient { pub fn to_unauth_client(&self) -> KanidmClient {

View file

@ -15,6 +15,7 @@
extern crate tracing; extern crate tracing;
use std::path::PathBuf; use std::path::PathBuf;
use uuid::Uuid; use uuid::Uuid;
include!("../opt/kanidm.rs"); include!("../opt/kanidm.rs");

View file

@ -13,7 +13,8 @@
use clap::Parser; use clap::Parser;
use kanidm_cli::KanidmClientParser; use kanidm_cli::KanidmClientParser;
use tracing_subscriber::{fmt, prelude::*, EnvFilter}; use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn main() { async fn main() {

View file

@ -1,22 +1,25 @@
use crate::password_prompt; use std::fmt::{self, Debug};
use crate::{ use std::str::FromStr;
AccountCredential, AccountRadius, AccountSsh, AccountValidity, PersonOpt, PersonPosix,
}; use dialoguer::theme::ColorfulTheme;
use dialoguer::{theme::ColorfulTheme, Select}; use dialoguer::{Confirm, Input, Password, Select};
use dialoguer::{Confirm, Input, Password};
use kanidm_client::ClientError::Http as ClientErrorHttp; use kanidm_client::ClientError::Http as ClientErrorHttp;
use kanidm_client::KanidmClient; use kanidm_client::KanidmClient;
use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus}; use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus};
use kanidm_proto::v1::OperationError::PasswordQuality; use kanidm_proto::v1::OperationError::PasswordQuality;
use kanidm_proto::v1::{CUIntentToken, CURegState, CUSessionToken, CUStatus, TotpSecret}; use kanidm_proto::v1::{CUIntentToken, CURegState, CUSessionToken, CUStatus, TotpSecret};
use qrcode::{render::unicode, QrCode}; use qrcode::render::unicode;
use std::fmt::{self, Debug}; use qrcode::QrCode;
use std::str::FromStr;
use time::OffsetDateTime; use time::OffsetDateTime;
use url::Url; use url::Url;
use uuid::Uuid; 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 { impl PersonOpt {
pub fn debug(&self) -> bool { pub fn debug(&self) -> bool {

View file

@ -1,14 +1,14 @@
use crate::RawOpt;
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path; use std::path::Path;
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use crate::RawOpt;
fn read_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> { fn read_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> {
let f = File::open(path)?; let f = File::open(path)?;
let r = BufReader::new(f); let r = BufReader::new(f);

View file

@ -1,9 +1,10 @@
use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus};
use time::OffsetDateTime;
use crate::{ use crate::{
AccountSsh, AccountValidity, ServiceAccountApiToken, ServiceAccountCredential, AccountSsh, AccountValidity, ServiceAccountApiToken, ServiceAccountCredential,
ServiceAccountOpt, ServiceAccountPosix, ServiceAccountOpt, ServiceAccountPosix,
}; };
use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus};
use time::OffsetDateTime;
impl ServiceAccountOpt { impl ServiceAccountOpt {
pub fn debug(&self) -> bool { pub fn debug(&self) -> bool {

View file

@ -1,23 +1,22 @@
use crate::common::prompt_for_username_get_username; use std::collections::BTreeMap;
use crate::{LoginOpt, LogoutOpt, SessionOpt}; 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_client::{ClientError, KanidmClient};
use kanidm_proto::v1::{AuthAllowed, AuthResponse, AuthState, UserAuthToken}; use kanidm_proto::v1::{AuthAllowed, AuthResponse, AuthState, UserAuthToken};
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
use libc::umask; use libc::umask;
use std::collections::BTreeMap; use webauthn_authenticator_rs::prelude::RequestChallengeResponse;
use std::fs::{create_dir, File}; use webauthn_authenticator_rs::u2fhid::U2FHid;
use std::io::ErrorKind; use webauthn_authenticator_rs::WebauthnAuthenticator;
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 dialoguer::{theme::ColorfulTheme, Select}; use crate::common::prompt_for_username_get_username;
use crate::{LoginOpt, LogoutOpt, SessionOpt};
use compact_jwt::JwsUnverified;
static TOKEN_DIR: &str = "~/.cache"; static TOKEN_DIR: &str = "~/.cache";
static TOKEN_PATH: &str = "~/.cache/kanidm_tokens"; static TOKEN_PATH: &str = "~/.cache/kanidm_tokens";

View file

@ -12,7 +12,6 @@ use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use kanidm_client::{ClientError, KanidmClientBuilder}; use kanidm_client::{ClientError, KanidmClientBuilder};
use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME}; use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME};
use tracing::{debug, error}; use tracing::{debug, error};

View file

@ -1,14 +1,15 @@
[package] [package]
name = "kanidm_unix_int" 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" description = "Kanidm Unix Integration Clients"
documentation = "https://docs.rs/kanidm/latest/kanidm/" 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] [lib]
name = "kanidm_unix_common" name = "kanidm_unix_common"
@ -43,46 +44,42 @@ name = "kanidm_test_auth"
path = "src/test_auth.rs" path = "src/test_auth.rs"
[dependencies] [dependencies]
kanidm_client = { path = "../kanidm_client" } bytes.workspace = true
kanidm_proto = { path = "../kanidm_proto" } clap = { workspace = true, features = ["derive", "env"] }
kanidm = { path = "../kanidmd/idm" } 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" r2d2.workspace = true
sketching = { path = "../sketching" } 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" toml.workspace = true
rpassword = "^7.0.0" tokio = { workspace = true, features = ["rt", "macros", "sync", "time", "net", "io-util"] }
tokio = { version = "^1.21.1", features = ["rt", "macros", "sync", "time", "net", "io-util"] } tokio-util = { workspace = true, features = ["codec"] }
tokio-util = { version = "^0.7.4", features = ["codec"] } tracing.workspace = true
reqwest.workspace = true
futures = "^0.3.21" users.workspace = true
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"
[features] [features]
# default = [ "libsqlite3-sys/bundled" ] # default = [ "libsqlite3-sys/bundled" ]
[dev-dependencies] [dev-dependencies]
# kanidm = { path = "../kanidmd/idm" } # kanidm = { path = "../kanidmd/idm" }
score = { path = "../kanidmd/score" } score.workspace = true
[build-dependencies] [build-dependencies]
clap = { version = "^3.2", features = ["derive"] } clap = { workspace = true, features = ["derive"] }
clap_complete = "^3.2.5" clap_complete.workspace = true
profiles = { path = "../profiles" } profiles.workspace = true

View file

@ -1,11 +1,10 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::env; use std::env;
use std::path::PathBuf;
use clap::{IntoApp, Parser}; use clap::{IntoApp, Parser};
use clap_complete::{generate_to, Shell}; use clap_complete::{generate_to, Shell};
use std::path::PathBuf;
include!("src/opt/ssh_authorizedkeys.rs"); include!("src/opt/ssh_authorizedkeys.rs");
include!("src/opt/cache_invalidate.rs"); include!("src/opt/cache_invalidate.rs");
include!("src/opt/cache_clear.rs"); include!("src/opt/cache_clear.rs");

View file

@ -1,9 +1,13 @@
[package] [package]
name = "nss_kanidm" name = "nss_kanidm"
version = "1.1.0-alpha.9"
authors = ["William Brown <william@blackhats.net.au>"] version.workspace = true
rust-version = "1.59" authors.workspace = true
edition = "2021" rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
[lib] [lib]
name = "nss_kanidm" name = "nss_kanidm"
@ -11,9 +15,9 @@ crate-type = [ "cdylib" ]
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
kanidm_unix_int = { path = "../" } kanidm_unix_int.workspace = true
libnss = "^0.4.0" libnss.workspace = true
libc = "^0.2.127" libc.workspace = true
paste = "^1.0.9" paste.workspace = true
lazy_static = "^1.4.0" lazy_static.workspace = true

View file

@ -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::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, NssGroup, NssUser}; use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, NssGroup, NssUser};
use libnss::group::{Group, GroupHooks}; use libnss::group::{Group, GroupHooks};
use libnss::interop::Response; use libnss::interop::Response;
use libnss::passwd::{Passwd, PasswdHooks}; use libnss::passwd::{Passwd, PasswdHooks};

View file

@ -1,19 +1,23 @@
[package] [package]
name = "pam_kanidm" name = "pam_kanidm"
version = "1.1.0-alpha.9"
authors = ["William Brown <william@blackhats.net.au>"]
rust-version = "1.59"
edition = "2021"
links = "pam" 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] [lib]
name = "pam_kanidm" name = "pam_kanidm"
crate-type = [ "cdylib" ] crate-type = [ "cdylib" ]
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
kanidm_unix_int = { path = "../" } kanidm_unix_int.workspace = true
libc = "^0.2.127" libc.workspace = true
[build-dependencies] [build-dependencies]
pkg-config = "^0.3.25" pkg-config.workspace = true

View file

@ -14,19 +14,20 @@
// extern crate libc; // extern crate libc;
mod pam; mod pam;
use crate::pam::constants::*;
use crate::pam::conv::PamConv;
use crate::pam::module::{PamHandle, PamHooks};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ffi::CStr; use std::ffi::CStr;
// use std::os::raw::c_char; // use std::os::raw::c_char;
use kanidm_unix_common::client_sync::call_daemon_blocking; use kanidm_unix_common::client_sync::call_daemon_blocking;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse}; 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)] #[derive(Debug)]
struct Options { struct Options {
debug: bool, debug: bool,

View file

@ -1,9 +1,9 @@
use libc::{c_char, c_int};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::ptr; use std::ptr;
use crate::pam::constants::PamResultCode; use libc::{c_char, c_int};
use crate::pam::constants::*;
use crate::pam::constants::{PamResultCode, *};
use crate::pam::module::{PamItem, PamResult}; use crate::pam::module::{PamItem, PamResult};
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]

View file

@ -7,10 +7,11 @@
/// Here is full example of a PAM module that would authenticate and authorize everybody: /// 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::{PamFlag, PamResultCode};
/// use pam::constants::{PamResultCode, PamFlag}; /// use pam::module::{PamHandle, PamHooks};
/// use std::ffi::CStr; /// use std::ffi::CStr;
/// ///
/// # fn main() {} /// # fn main() {}
@ -36,6 +37,7 @@ macro_rules! pam_hooks {
mod pam_hooks_scope { mod pam_hooks_scope {
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use $crate::pam::constants::{PamFlag, PamResultCode}; use $crate::pam::constants::{PamFlag, PamResultCode};
use $crate::pam::module::{PamHandle, PamHooks}; use $crate::pam::module::{PamHandle, PamHooks};

View file

@ -1,9 +1,10 @@
//! Functions for use in pam modules. //! Functions for use in pam modules.
use libc::c_char;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::{mem, ptr}; use std::{mem, ptr};
use libc::c_char;
use crate::pam::constants::{PamFlag, PamItemType, PamResultCode, PAM_AUTHTOK}; use crate::pam::constants::{PamFlag, PamItemType, PamResultCode, PAM_AUTHTOK};
/// Opaque type, used as a pointer when making pam API calls. /// Opaque type, used as a pointer when making pam API calls.

View file

@ -1,11 +1,14 @@
[package] [package]
name = "pam_tester" 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] [dependencies]
pam = "^0.7.0" pam = "^0.7.0"

View file

@ -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::collections::BTreeSet;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::ops::{Add, Sub}; use std::ops::{Add, Sub};
use std::path::Path; use std::path::Path;
use std::string::ToString; use std::string::ToString;
use std::time::{Duration, SystemTime}; 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 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; const NXCACHE_SIZE: usize = 2048;
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]

View file

@ -14,9 +14,7 @@
extern crate tracing; extern crate tracing;
use clap::Parser; use clap::Parser;
use futures::executor::block_on; use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;

View file

@ -14,9 +14,7 @@
extern crate tracing; extern crate tracing;
use clap::Parser; use clap::Parser;
use futures::executor::block_on; use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;

View file

@ -1,9 +1,8 @@
use bytes::{BufMut, BytesMut};
use futures::SinkExt;
use futures::StreamExt;
use std::error::Error; use std::error::Error;
use std::io::Error as IoError; use std::io::{Error as IoError, ErrorKind};
use std::io::ErrorKind;
use bytes::{BufMut, BytesMut};
use futures::{SinkExt, StreamExt};
use tokio::net::UnixStream; use tokio::net::UnixStream;
// use tokio::runtime::Builder; // use tokio::runtime::Builder;
use tokio_util::codec::Framed; use tokio_util::codec::Framed;
@ -14,8 +13,8 @@ use crate::unix_proto::{ClientRequest, ClientResponse};
struct ClientCodec; struct ClientCodec;
impl Decoder for ClientCodec { impl Decoder for ClientCodec {
type Item = ClientResponse;
type Error = IoError; type Error = IoError;
type Item = ClientResponse;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> { fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match serde_json::from_slice::<ClientResponse>(&src) { match serde_json::from_slice::<ClientResponse>(&src) {

View file

@ -1,9 +1,6 @@
use std::error::Error; use std::error::Error;
use std::io::Error as IoError; use std::io::{Error as IoError, ErrorKind, Read, Write};
use std::io::ErrorKind;
use std::io::{Read, Write};
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use crate::unix_proto::{ClientRequest, ClientResponse}; use crate::unix_proto::{ClientRequest, ClientResponse};

View file

@ -10,10 +10,18 @@
#![deny(clippy::needless_pass_by_value)] #![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)] #![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 bytes::{BufMut, BytesMut};
use clap::{Arg, ArgAction, Command}; use clap::{Arg, ArgAction, Command};
use futures::SinkExt; use futures::{SinkExt, StreamExt};
use futures::StreamExt;
use kanidm::utils::file_permissions_readonly; use kanidm::utils::file_permissions_readonly;
use kanidm_client::KanidmClientBuilder; use kanidm_client::KanidmClientBuilder;
use kanidm_proto::constants::DEFAULT_CLIENT_CONFIG_PATH; 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_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse}; use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse};
use libc::umask; use libc::umask;
use sketching::tracing_forest::{self, traits::*, util::*}; use sketching::tracing_forest::traits::*;
use std::error::Error; use sketching::tracing_forest::util::*;
use std::fs::metadata; use sketching::tracing_forest::{self};
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 tokio::net::{UnixListener, UnixStream}; use tokio::net::{UnixListener, UnixStream};
use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tokio::time; use tokio::time;
use tokio_util::codec::Framed; use tokio_util::codec::{Decoder, Encoder, Framed};
use tokio_util::codec::{Decoder, Encoder};
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
//=== the codec //=== the codec
@ -47,8 +47,8 @@ type AsyncTaskRequest = (TaskRequest, oneshot::Sender<()>);
struct ClientCodec; struct ClientCodec;
impl Decoder for ClientCodec { impl Decoder for ClientCodec {
type Item = ClientRequest;
type Error = io::Error; type Error = io::Error;
type Item = ClientRequest;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> { fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match serde_json::from_slice::<ClientRequest>(&src) { match serde_json::from_slice::<ClientRequest>(&src) {
@ -85,8 +85,8 @@ impl ClientCodec {
struct TaskCodec; struct TaskCodec;
impl Decoder for TaskCodec { impl Decoder for TaskCodec {
type Item = TaskResponse;
type Error = io::Error; type Error = io::Error;
type Item = TaskResponse;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> { fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match serde_json::from_slice::<TaskResponse>(&src) { match serde_json::from_slice::<TaskResponse>(&src) {

View file

@ -13,12 +13,10 @@
#[macro_use] #[macro_use]
extern crate tracing; extern crate tracing;
use clap::Parser;
use std::path::PathBuf; use std::path::PathBuf;
use clap::Parser;
// use futures::executor::block_on; // use futures::executor::block_on;
use kanidm_unix_common::client_sync::call_daemon_blocking; use kanidm_unix_common::client_sync::call_daemon_blocking;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;

View file

@ -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::convert::TryFrom;
use std::fmt; use std::fmt;
use std::time::Duration; use std::time::Duration;
use crate::cache::Id;
use tokio::sync::{Mutex, MutexGuard};
use kanidm::be::dbvalue::DbPasswordV1; use kanidm::be::dbvalue::DbPasswordV1;
use kanidm::credential::policy::CryptoPolicy; use kanidm::credential::policy::CryptoPolicy;
use kanidm::credential::Password; 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 { pub struct Db {
pool: Pool<SqliteConnectionManager>, pool: Pool<SqliteConnectionManager>,
@ -732,9 +732,10 @@ impl<'a> Drop for DbTxn<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
use super::Db; use super::Db;
use crate::cache::Id; use crate::cache::Id;
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test"; const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test";
const TESTACCOUNT1_PASSWORD_B: &str = "password b for account1 test"; const TESTACCOUNT1_PASSWORD_B: &str = "password b for account1 test";

View file

@ -13,11 +13,10 @@
#[macro_use] #[macro_use]
extern crate tracing; extern crate tracing;
use clap::Parser;
use std::path::PathBuf; use std::path::PathBuf;
use clap::Parser;
use futures::executor::block_on; use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;

View file

@ -10,35 +10,31 @@
#![deny(clippy::needless_pass_by_value)] #![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)] #![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 std::ffi::CString;
use std::os::unix::fs::symlink;
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::path::Path; use std::path::Path;
use std::time::Duration; use std::time::Duration;
use tokio::net::UnixStream; use std::{fs, io};
use tokio::time;
use tokio_util::codec::Framed;
use tokio_util::codec::{Decoder, Encoder};
use bytes::{BufMut, BytesMut};
use futures::{SinkExt, StreamExt};
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{HomeDirectoryInfo, TaskRequest, TaskResponse}; 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; struct TaskCodec;
impl Decoder for TaskCodec { impl Decoder for TaskCodec {
type Item = TaskRequest;
type Error = io::Error; type Error = io::Error;
type Item = TaskRequest;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> { fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match serde_json::from_slice::<TaskRequest>(&src) { match serde_json::from_slice::<TaskRequest>(&src) {

View file

@ -3,9 +3,7 @@
extern crate tracing; extern crate tracing;
use clap::Parser; use clap::Parser;
use futures::executor::block_on; use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;

View file

@ -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::env;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::fs::File; use std::fs::File;
use std::io::{ErrorKind, Read}; use std::io::{ErrorKind, Read};
use std::path::Path; 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)] #[derive(Debug, Deserialize)]
struct ConfigInt { struct ConfigInt {
db_path: Option<String>, db_path: Option<String>,

View file

@ -1,23 +1,19 @@
#![deny(warnings)] #![deny(warnings)]
use std::future::Future;
use std::net::TcpStream; use std::net::TcpStream;
use std::pin::Pin;
use std::sync::atomic::{AtomicU16, Ordering}; use std::sync::atomic::{AtomicU16, Ordering};
use std::time::Duration; use std::time::Duration;
use kanidm::audit::LogLevel; use kanidm::audit::LogLevel;
use kanidm::config::{Configuration, IntegrationTestConfig, ServerRole}; 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::cache::{CacheLayer, Id};
use kanidm_unix_common::constants::{ use kanidm_unix_common::constants::{
DEFAULT_GID_ATTR_MAP, DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_GID_ATTR_MAP, DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX,
DEFAULT_SHELL, DEFAULT_UID_ATTR_MAP, DEFAULT_SHELL, DEFAULT_UID_ATTR_MAP,
}; };
use score::create_server_core;
use kanidm_client::{KanidmClient, KanidmClientBuilder};
use std::future::Future;
use std::pin::Pin;
use tokio::task; use tokio::task;
static PORT_ALLOC: AtomicU16 = AtomicU16::new(28080); static PORT_ALLOC: AtomicU16 = AtomicU16::new(28080);

View file

@ -1,14 +1,15 @@
[package] [package]
name = "daemon" 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" description = "Kanidm Server Daemon"
documentation = "https://docs.rs/kanidm/latest/kanidm/" 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 # 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" path = "src/main.rs"
[dependencies] [dependencies]
kanidm = { path = "../idm" } kanidm.workspace = true
kanidm_proto = { path = "../../kanidm_proto" } kanidm_proto.workspace = true
score = { path = "../score" } score.workspace = true
sketching = { path = "../../sketching" } sketching.workspace = true
clap = { version = "^3.2", features = ["derive", "env"] } clap = { workspace = true, features = ["env"] }
serde = { version = "^1.0.142", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
tokio = { version = "^1.21.1", features = ["rt-multi-thread", "macros", "signal"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal"] }
toml = "0.5.9" toml.workspace = true
[target.'cfg(target_family = "windows")'.dependencies] [target.'cfg(target_family = "windows")'.dependencies]
whoami = "^1.2.3" whoami.workspace = true
[target.'cfg(not(target_family = "windows"))'.dependencies] [target.'cfg(not(target_family = "windows"))'.dependencies]
users = "^0.11.0" users.workspace = true
tikv-jemallocator = "0.5" tikv-jemallocator.workspace = true
[build-dependencies] [build-dependencies]
serde = { version = "1", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
clap = { version = "^3.2", features = ["derive"] } clap = { workspace = true, features = ["derive"] }
clap_complete = "^3.2.5" clap_complete.workspace = true
profiles = { path = "../../profiles" } profiles.workspace = true

View file

@ -5,7 +5,6 @@ use std::path::PathBuf;
use clap::{Args, IntoApp, Parser, Subcommand}; use clap::{Args, IntoApp, Parser, Subcommand};
use clap_complete::{generate_to, Shell}; use clap_complete::{generate_to, Shell};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
include!("../idm/src/audit_loglevel.rs"); include!("../idm/src/audit_loglevel.rs");

View file

@ -14,25 +14,15 @@
#[global_allocator] #[global_allocator]
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; 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::fs::{metadata, File, Metadata};
use std::io::Read;
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use std::io::Read;
use std::path::Path;
use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use std::str::FromStr; use std::str::FromStr;
use sketching::tracing_forest::{self, traits::*, util::*}; use clap::{Args, Parser, Subcommand};
use kanidm::audit::LogLevel; use kanidm::audit::LogLevel;
use kanidm::config::{Configuration, OnlineBackup, ServerRole}; use kanidm::config::{Configuration, OnlineBackup, ServerRole};
#[cfg(not(target_family = "windows"))] #[cfg(not(target_family = "windows"))]
@ -43,8 +33,14 @@ use score::{
domain_rename_core, recover_account_core, reindex_server_core, restore_server_core, domain_rename_core, recover_account_core, reindex_server_core, restore_server_core,
vacuum_server_core, verify_server_core, vacuum_server_core, verify_server_core,
}; };
use serde::Deserialize;
use clap::{Args, Parser, Subcommand}; 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"); include!("./opt.rs");

View file

@ -1,98 +1,91 @@
[package] [package]
name = "kanidm" 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" description = "Kanidm Server Library and Binary"
documentation = "https://docs.rs/kanidm/latest/kanidm/" 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] [lib]
name = "kanidm" name = "kanidm"
path = "src/lib.rs" path = "src/lib.rs"
[[bench]]
name = "scaling_10k"
harness = false
[dependencies] [dependencies]
async-std = { version = "^1.12.0", features = ["tokio1"] } async-std.workspace = true
async-trait = "^0.1.57" async-trait.workspace = true
base64 = "^0.13.0" base64.workspace = true
base64urlsafedata = "0.1.0" base64urlsafedata.workspace = true
chrono = "^0.4.20" chrono.workspace = true
compact_jwt = "^0.2.3" compact_jwt.workspace = true
concread = "^0.4.0" concread.workspace = true
dyn-clone = "^1.0.9" dyn-clone.workspace = true
fernet = { version = "^0.2.0", features = ["fernet_danger_timestamps"] } fernet = { workspace = true, features = ["fernet_danger_timestamps"] }
filetime = "^0.2.17" filetime.workspace = true
futures = "^0.3.21" futures.workspace = true
futures-util = "^0.3.21" futures-util.workspace = true
hashbrown = { version = "0.12.3", features = ["serde", "inline-more", "ahash"] } hashbrown.workspace = true
idlset = { version = "^0.2.4" } idlset.workspace = true
kanidm_proto = { path = "../../kanidm_proto" } kanidm_proto.workspace = true
lazy_static = "^1.4.0" lazy_static.workspace = true
ldap3_proto = "^0.2.3" ldap3_proto.workspace = true
libc = "^0.2.127" libc.workspace = true
libsqlite3-sys = "^0.25.0" libsqlite3-sys.workspace = true
num_enum = "^0.5.7" num_enum.workspace = true
openssl = "^0.10.41" openssl.workspace = true
r2d2 = "^0.8.9" r2d2.workspace = true
r2d2_sqlite = "^0.21.0" r2d2_sqlite.workspace = true
rand = "^0.8.5" rand.workspace = true
regex = "^1.5.6" regex.workspace = true
saffron = "^0.1.0" saffron.workspace = true
serde = { version = "^1.0.142", features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_cbor = "^0.11.2" serde_cbor.workspace = true
serde_json = "^1.0.83" serde_json.workspace = true
smartstring = { version = "^1.0.1", features = ["serde"] } sketching.workspace = true
smolset = "^1.3.1" smartstring = { workspace = true, features = ["serde"] }
sshkeys = "^0.3.1" smolset.workspace = true
tide = "^0.16.0" sshkeys.workspace = true
time = { version = "=0.2.27", features = ["serde", "std"] } tide.workspace = true
tokio = { version = "^1.21.1", features = ["net", "sync", "time"] } time = { workspace = true, features = ["serde", "std"] }
tokio-util = { version = "^0.7.4", features = ["codec"] } tokio = { workspace = true, features = ["net", "sync", "time"] }
toml = "^0.5.9" tokio-util = { workspace = true, features = ["codec"] }
touch = "^0.0.1" toml.workspace = true
touch.workspace = true
sketching = { path = "../../sketching" } tracing = { workspace = true, features = ["attributes"] }
tracing = { version = "^0.1.35", features = ["attributes"] }
url = { version = "^2.3.1", features = ["serde"] } url = { workspace = true, features = ["serde"] }
urlencoding = "2.1.2" urlencoding.workspace = true
uuid = { version = "^1.1.2", features = ["serde", "v4" ] } uuid = { workspace = true, features = ["serde", "v4" ] }
validator = { version = "^0.16.0", features = ["phone"] } validator = { workspace = true, features = ["phone"] }
webauthn-rs = { workspace = true, features = ["resident-key-support", "preview-features", "danger-credential-internals"] } webauthn-rs = { workspace = true, features = ["resident-key-support", "preview-features", "danger-credential-internals"] }
webauthn-rs-core.workspace = true webauthn-rs-core.workspace = true
zxcvbn = "^2.2.1" zxcvbn.workspace = true
# because windows really can't build without the bundled one # 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] [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] [target.'cfg(not(target_family = "windows"))'.dependencies]
users = "^0.11.0" rusqlite.workspace = true
users.workspace = true
[features] [features]
# default = [ "libsqlite3-sys/bundled", "openssl/vendored" ] # default = [ "libsqlite3-sys/bundled", "openssl/vendored" ]
[dev-dependencies] [dev-dependencies]
criterion = { version = "^0.4.0", features = ["html_reports"] } criterion = { workspace = true, features = ["html_reports"] }
# For testing webauthn
webauthn-authenticator-rs.workspace = true webauthn-authenticator-rs.workspace = true
[build-dependencies] [build-dependencies]
profiles = { path = "../../profiles" } profiles.workspace = true
[[bench]]
name = "scaling_10k"
harness = false

View file

@ -1,7 +1,9 @@
use std::time::{Duration, Instant};
use async_std::task;
use criterion::{ use criterion::{
criterion_group, criterion_main, BenchmarkId, Criterion, SamplingMode, Throughput, criterion_group, criterion_main, BenchmarkId, Criterion, SamplingMode, Throughput,
}; };
use kanidm; use kanidm;
use kanidm::entry::{Entry, EntryInit, EntryNew}; use kanidm::entry::{Entry, EntryInit, EntryNew};
use kanidm::entry_init; use kanidm::entry_init;
@ -11,9 +13,6 @@ use kanidm::server::QueryServer;
use kanidm::utils::duration_from_epoch_now; use kanidm::utils::duration_from_epoch_now;
use kanidm::value::Value; use kanidm::value::Value;
use async_std::task;
use std::time::{Duration, Instant};
pub fn scaling_user_create_single(c: &mut Criterion) { pub fn scaling_user_create_single(c: &mut Criterion) {
let mut group = c.benchmark_group("user_create_single"); let mut group = c.benchmark_group("user_create_single");
group.sample_size(10); group.sample_size(10);

View file

@ -12,31 +12,28 @@
//! search. //! search.
//! - the ability to turn an entry into a partial-entry for results send //! - the ability to turn an entry into a partial-entry for results send
//! requirements (also search). //! requirements (also search).
//!
// use concread::collections::bptree::*; // 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 hashbrown::HashSet;
use std::cell::Cell; use std::cell::Cell;
use std::collections::BTreeSet;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::sync::Arc; 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 uuid::Uuid;
use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced, EntrySealed};
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent};
use crate::filter::{Filter, FilterValid, FilterValidResolved}; use crate::filter::{Filter, FilterValid, FilterValidResolved};
use crate::identity::{IdentType, IdentityId};
use crate::modify::Modify; use crate::modify::Modify;
use crate::prelude::*; use crate::prelude::*;
use crate::value::PartialValue; 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_MAX: usize = 2048;
// const ACP_RELATED_SEARCH_CACHE_LOCAL: usize = 16; // const ACP_RELATED_SEARCH_CACHE_LOCAL: usize = 16;
@ -408,6 +405,7 @@ pub trait AccessControlsTransaction<'a> {
&self, &self,
) -> &mut ARCacheReadTxn<'a, (IdentityId, Filter<FilterValid>), Filter<FilterValidResolved>, ()>; ) -> &mut ARCacheReadTxn<'a, (IdentityId, Filter<FilterValid>), Filter<FilterValidResolved>, ()>;
#[instrument(level = "debug", name = "access::search_related_acp", skip_all)]
fn search_related_acp<'b>( fn search_related_acp<'b>(
&'b self, &'b self,
rec_entry: &Entry<EntrySealed, EntryCommitted>, rec_entry: &Entry<EntrySealed, EntryCommitted>,
@ -443,9 +441,7 @@ pub trait AccessControlsTransaction<'a> {
} else { } else {
*/ */
// else, we calculate this, and then stash/cache the uuids. // else, we calculate this, and then stash/cache the uuids.
let related_acp: Vec<(&AccessControlSearch, Filter<FilterValidResolved>)> = let related_acp: Vec<(&AccessControlSearch, Filter<FilterValidResolved>)> = search_state
spanned!("access::search_related_acp<uncached>", {
search_state
.iter() .iter()
.filter_map(|acs| { .filter_map(|acs| {
// Now resolve the receiver filter // Now resolve the receiver filter
@ -463,11 +459,7 @@ pub trait AccessControlsTransaction<'a> {
// A possible solution is to change the filter resolve function // A possible solution is to change the filter resolve function
// such that it takes an entry, rather than an event, but that // such that it takes an entry, rather than an event, but that
// would create issues in search. // would create issues in search.
match (&acs.acp.receiver).resolve( match (&acs.acp.receiver).resolve(ident, None, Some(acp_resolve_filter_cache)) {
ident,
None,
Some(acp_resolve_filter_cache),
) {
Ok(f_res) => { Ok(f_res) => {
if rec_entry.entry_match_no_index(&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 // Now, for each of the acp's that apply to our receiver, resolve their
@ -488,16 +480,12 @@ pub trait AccessControlsTransaction<'a> {
} }
} }
Err(e) => { Err(e) => {
admin_error!( admin_error!(?e, "A internal filter/event was passed for resolution!?!?");
?e,
"A internal filter/event was passed for resolution!?!?"
);
None None
} }
} }
}) })
.collect() .collect();
});
/* /*
// Stash the uuids into the cache. // Stash the uuids into the cache.
@ -511,6 +499,7 @@ pub trait AccessControlsTransaction<'a> {
} }
// Contains all the way to eval acps to entries // Contains all the way to eval acps to entries
#[instrument(level = "debug", name = "access::search_filter_entries", skip_all)]
fn search_filter_entries( fn search_filter_entries(
&self, &self,
se: &SearchEvent, se: &SearchEvent,
@ -525,7 +514,6 @@ pub trait AccessControlsTransaction<'a> {
} }
IdentType::User(u) => &u.entry, IdentType::User(u) => &u.entry,
}; };
spanned!("access::search_filter_entries", {
trace!(event = %se.ident, "Access check for search (filter) event"); trace!(event = %se.ident, "Access check for search (filter) event");
// First get the set of acps that apply to this receiver // 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(); let requested_attrs: BTreeSet<&str> = se.filter_orig.get_attr_set();
// For each entry // For each entry
let allowed_entries: Vec<Arc<EntrySealedCommitted>> = spanned!( let allowed_entries: Vec<Arc<EntrySealedCommitted>> =
"access::search_filter_entries<allowed_entries>",
{
entries entries
.into_iter() .into_iter()
.filter(|e| { .filter(|e| {
@ -580,9 +566,7 @@ pub trait AccessControlsTransaction<'a> {
security_access!(?decision, "search attr decision"); security_access!(?decision, "search attr decision");
decision decision
}) })
.collect() .collect();
}
);
if allowed_entries.is_empty() { if allowed_entries.is_empty() {
security_access!("denied ❌"); security_access!("denied ❌");
@ -591,9 +575,13 @@ pub trait AccessControlsTransaction<'a> {
} }
Ok(allowed_entries) Ok(allowed_entries)
})
} }
#[instrument(
level = "debug",
name = "access::search_filter_entry_attributes",
skip_all
)]
fn search_filter_entry_attributes( fn search_filter_entry_attributes(
&self, &self,
se: &SearchEvent, se: &SearchEvent,
@ -620,7 +608,6 @@ pub trait AccessControlsTransaction<'a> {
IdentType::User(u) => &u.entry, 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, * 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 * 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. // Get the relevant acps for this receiver.
let related_acp: Vec<(&AccessControlSearch, _)> = let related_acp: Vec<(&AccessControlSearch, _)> =
self.search_related_acp(rec_entry, &se.ident); self.search_related_acp(rec_entry, &se.ident);
let related_acp: Vec<(&AccessControlSearch, _)> = let related_acp: Vec<(&AccessControlSearch, _)> = if let Some(r_attrs) = se.attrs.as_ref() {
if let Some(r_attrs) = se.attrs.as_ref() {
related_acp related_acp
.into_iter() .into_iter()
.filter(|(acs, _)| !acs.attrs.is_disjoint(r_attrs)) .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()); .map(|vs| vs.iter().map(|s| s.as_str()).collect());
// For each entry // For each entry
let allowed_entries: Vec<Entry<EntryReduced, EntryCommitted>> = let allowed_entries: Vec<Entry<EntryReduced, EntryCommitted>> = entries
spanned!("access::search_filter_entry_attributes<allowed_entries>", {
entries
.into_iter() .into_iter()
.map(|e| { .map(|e| {
// Get the set of attributes you can see for this entry // 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. // Now purge the attrs that are NOT allowed.
spanned!( e.reduce_attributes(&allowed_attrs)
"access::search_filter_entry_attributes<reduce_attributes>",
{ e.reduce_attributes(&allowed_attrs) }
)
}) })
.collect() .collect();
});
if allowed_entries.is_empty() { if allowed_entries.is_empty() {
security_access!("reduced to empty set on all entries ❌"); security_access!("reduced to empty set on all entries ❌");
@ -719,9 +699,9 @@ pub trait AccessControlsTransaction<'a> {
} }
Ok(allowed_entries) Ok(allowed_entries)
})
} }
#[instrument(level = "debug", name = "access::modify_related_acp", skip_all)]
fn modify_related_acp<'b>( fn modify_related_acp<'b>(
&'b self, &'b self,
rec_entry: &Entry<EntrySealed, EntryCommitted>, 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 // Find the acps that relate to the caller, and compile their related
// target filters. // target filters.
let related_acp: Vec<(&AccessControlModify, _)> = spanned!( let related_acp: Vec<(&AccessControlModify, _)> =
"access::modify_related_acp<uncached>",
{
modify_state modify_state
.iter() .iter()
.filter_map(|acs| { .filter_map(|acs| {
@ -766,14 +744,13 @@ pub trait AccessControlsTransaction<'a> {
} }
} }
}) })
.collect() .collect();
}
);
related_acp related_acp
} }
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
#[instrument(level = "debug", name = "access::modify_allow_operation", skip_all)]
fn modify_allow_operation( fn modify_allow_operation(
&self, &self,
me: &ModifyEvent, me: &ModifyEvent,
@ -787,7 +764,6 @@ pub trait AccessControlsTransaction<'a> {
} }
IdentType::User(u) => &u.entry, IdentType::User(u) => &u.entry,
}; };
spanned!("access::modify_allow_operation", {
trace!("Access check for modify event: {}", me.ident); trace!("Access check for modify event: {}", me.ident);
// Pre-check if the no-no purge class is present // Pre-check if the no-no purge class is present
@ -932,10 +908,10 @@ pub trait AccessControlsTransaction<'a> {
security_access!("denied ❌"); security_access!("denied ❌");
} }
Ok(r) Ok(r)
})
} }
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
#[instrument(level = "debug", name = "access::create_allow_operation", skip_all)]
fn create_allow_operation( fn create_allow_operation(
&self, &self,
ce: &CreateEvent, ce: &CreateEvent,
@ -949,7 +925,6 @@ pub trait AccessControlsTransaction<'a> {
} }
IdentType::User(u) => &u.entry, IdentType::User(u) => &u.entry,
}; };
spanned!("access::create_allow_operation", {
trace!("Access check for create event: {}", ce.ident); trace!("Access check for create event: {}", ce.ident);
// Some useful references we'll use for the remainder of the operation // Some useful references we'll use for the remainder of the operation
@ -1065,9 +1040,9 @@ pub trait AccessControlsTransaction<'a> {
} }
Ok(r) Ok(r)
})
} }
#[instrument(level = "debug", name = "access::delete_allow_operation", skip_all)]
fn delete_allow_operation( fn delete_allow_operation(
&self, &self,
de: &DeleteEvent, de: &DeleteEvent,
@ -1081,7 +1056,6 @@ pub trait AccessControlsTransaction<'a> {
} }
IdentType::User(u) => &u.entry, IdentType::User(u) => &u.entry,
}; };
spanned!("access::delete_allow_operation", {
trace!("Access check for delete event: {}", de.ident); trace!("Access check for delete event: {}", de.ident);
// Some useful references we'll use for the remainder of the operation // Some useful references we'll use for the remainder of the operation
@ -1158,9 +1132,9 @@ pub trait AccessControlsTransaction<'a> {
security_access!("denied ❌"); security_access!("denied ❌");
} }
Ok(r) Ok(r)
})
} }
#[instrument(level = "debug", name = "access::effective_permission_check", skip_all)]
fn effective_permission_check( fn effective_permission_check(
&self, &self,
ident: &Identity, ident: &Identity,
@ -1186,7 +1160,6 @@ pub trait AccessControlsTransaction<'a> {
IdentType::User(u) => &u.entry, IdentType::User(u) => &u.entry,
}; };
spanned!("access::effective_permission_check", {
trace!(ident = %ident, "Effective permission check"); trace!(ident = %ident, "Effective permission check");
// I think we seperate this to multiple checks ...? // I think we seperate this to multiple checks ...?
@ -1295,7 +1268,6 @@ pub trait AccessControlsTransaction<'a> {
}); });
Ok(effective_permissions) Ok(effective_permissions)
})
} }
} }
@ -1522,15 +1494,17 @@ impl AccessControls {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::BTreeSet;
use std::sync::Arc;
use uuid::uuid;
use crate::access::{ use crate::access::{
AccessControlCreate, AccessControlDelete, AccessControlModify, AccessControlProfile, AccessControlCreate, AccessControlDelete, AccessControlModify, AccessControlProfile,
AccessControlSearch, AccessControls, AccessControlsTransaction, AccessEffectivePermission, AccessControlSearch, AccessControls, AccessControlsTransaction, AccessEffectivePermission,
}; };
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent};
use crate::prelude::*; use crate::prelude::*;
use std::collections::BTreeSet;
use std::sync::Arc;
use uuid::uuid;
macro_rules! acp_from_entry_err { macro_rules! acp_from_entry_err {
( (

View file

@ -1,23 +1,28 @@
use tracing::{error, info, instrument, trace}; use std::convert::TryFrom;
use std::fs;
use chrono::{DateTime, SecondsFormat, Utc}; use std::path::{Path, PathBuf};
use std::sync::Arc; 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::be::BackendTransaction;
use crate::event::{ use crate::event::{
AuthEvent, AuthResult, OnlineBackupEvent, SearchEvent, SearchResult, WhoamiResult, AuthEvent, AuthResult, OnlineBackupEvent, SearchEvent, SearchResult, WhoamiResult,
}; };
use crate::filter::{Filter, FilterInvalid};
use crate::idm::credupdatesession::CredentialUpdateSessionToken; use crate::idm::credupdatesession::CredentialUpdateSessionToken;
use crate::idm::event::{ use crate::idm::event::{
CredentialStatusEvent, RadiusAuthTokenEvent, ReadBackupCodeEvent, UnixGroupTokenEvent, CredentialStatusEvent, RadiusAuthTokenEvent, ReadBackupCodeEvent, UnixGroupTokenEvent,
UnixUserAuthEvent, UnixUserTokenEvent, UnixUserAuthEvent, UnixUserTokenEvent,
}; };
use kanidm_proto::v1::{BackupCodesView, OperationError, RadiusAuthToken};
use crate::filter::{Filter, FilterInvalid};
use crate::idm::oauth2::{ use crate::idm::oauth2::{
AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest, AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest,
AccessTokenResponse, AuthorisationRequest, AuthorisePermitSuccess, AuthoriseResponse, AccessTokenResponse, AuthorisationRequest, AuthorisePermitSuccess, AuthoriseResponse,
@ -26,20 +31,7 @@ use crate::idm::oauth2::{
use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::idm::server::{IdmServer, IdmServerTransaction};
use crate::idm::serviceaccount::ListApiTokenEvent; use crate::idm::serviceaccount::ListApiTokenEvent;
use crate::ldap::{LdapBoundToken, LdapResponseState, LdapServer}; use crate::ldap::{LdapBoundToken, LdapResponseState, LdapServer};
use crate::prelude::*;
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;
// =========================================================== // ===========================================================
@ -94,14 +86,6 @@ impl QueryServerReadV1 {
// Begin a read // Begin a read
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; 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 let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -121,8 +105,6 @@ impl QueryServerReadV1 {
let entries = idms_prox_read.qs_read.search_ext(&search)?; let entries = idms_prox_read.qs_read.search_ext(&search)?;
SearchResult::new(&idms_prox_read.qs_read, &entries).map(SearchResult::response) SearchResult::new(&idms_prox_read.qs_read, &entries).map(SearchResult::response)
});
res
} }
#[instrument( #[instrument(
@ -184,21 +166,22 @@ impl QueryServerReadV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
trace!(eventid = ?msg.eventid, "Begin online backup event"); trace!(eventid = ?msg.eventid, "Begin online backup event");
let now: DateTime<Utc> = Utc::now(); #[allow(deprecated)]
let timestamp = now.to_rfc3339_opts(SecondsFormat::Secs, true); let now = time::OffsetDateTime::now_local();
let timestamp = now.format(time::Format::Rfc3339);
let dest_file = format!("{}/backup-{}.json", outpath, timestamp); let dest_file = format!("{}/backup-{}.json", outpath, timestamp);
match Path::new(&dest_file).exists() { if Path::new(&dest_file).exists() {
true => {
error!( error!(
"Online backup file {} already exists, will not owerwrite it.", "Online backup file {} already exists, will not overwrite it.",
dest_file dest_file
); );
return Err(OperationError::InvalidState); return Err(OperationError::InvalidState);
} }
false => {
// Scope to limit the read txn.
{
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
spanned!("actors::v1_read::handle<OnlineBackupEvent>", {
idms_prox_read idms_prox_read
.qs_read .qs_read
.get_be_txn() .get_be_txn()
@ -210,8 +193,6 @@ impl QueryServerReadV1 {
error!("Online backup failed to create {}: {:?}", dest_file, e); error!("Online backup failed to create {}: {:?}", dest_file, e);
OperationError::InvalidState OperationError::InvalidState
})?; })?;
});
}
} }
// pattern to find automatically generated backup files // pattern to find automatically generated backup files
@ -314,14 +295,6 @@ impl QueryServerReadV1 {
// Begin a read // Begin a read
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; 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 // Make an event from the whoami request. This will process the event and
// generate a selfuuid search. // generate a selfuuid search.
// //
@ -350,17 +323,14 @@ impl QueryServerReadV1 {
Some(e) if entries.is_empty() => { Some(e) if entries.is_empty() => {
WhoamiResult::new(&idms_prox_read.qs_read, &e).map(WhoamiResult::response) 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), _ => Err(OperationError::NoMatchingEntries),
} }
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "search2", skip_all,
skip(self, uat, filter, attrs, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalsearch( pub async fn handle_internalsearch(
@ -372,7 +342,6 @@ impl QueryServerReadV1 {
) -> Result<Vec<ProtoEntry>, OperationError> { ) -> Result<Vec<ProtoEntry>, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<InternalSearchMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -400,14 +369,11 @@ impl QueryServerReadV1 {
.map(|ok_sr| ok_sr.into_proto_array()), .map(|ok_sr| ok_sr.into_proto_array()),
Err(e) => Err(e), Err(e) => Err(e),
} }
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "search_recycled", skip_all,
skip(self, uat, filter, attrs, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalsearchrecycled( pub async fn handle_internalsearchrecycled(
@ -420,7 +386,6 @@ impl QueryServerReadV1 {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<InternalSearchRecycledMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -448,14 +413,11 @@ impl QueryServerReadV1 {
.map(|ok_sr| ok_sr.into_proto_array()), .map(|ok_sr| ok_sr.into_proto_array()),
Err(e) => Err(e), Err(e) => Err(e),
} }
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "radius_read", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalradiusread( pub async fn handle_internalradiusread(
@ -466,7 +428,6 @@ impl QueryServerReadV1 {
) -> Result<Option<String>, OperationError> { ) -> Result<Option<String>, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<InternalRadiusReadMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -512,14 +473,11 @@ impl QueryServerReadV1 {
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "radius_token_read", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalradiustokenread( pub async fn handle_internalradiustokenread(
@ -531,7 +489,6 @@ impl QueryServerReadV1 {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_read = self.idms.proxy_read_async().await; let mut idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<InternalRadiusTokenReadMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -563,14 +520,11 @@ impl QueryServerReadV1 {
trace!(?rate, "Begin event"); trace!(?rate, "Begin event");
idms_prox_read.get_radiusauthtoken(&rate, ct) idms_prox_read.get_radiusauthtoken(&rate, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "unix_user_token_read", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalunixusertokenread( pub async fn handle_internalunixusertokenread(
@ -582,9 +536,6 @@ impl QueryServerReadV1 {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_read = self.idms.proxy_read_async().await; let mut idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!(
"actors::v1_read::handle<InternalUnixUserTokenReadMessage>",
{
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -617,14 +568,10 @@ impl QueryServerReadV1 {
idms_prox_read.get_unixusertoken(&rate, ct) idms_prox_read.get_unixusertoken(&rate, ct)
} }
);
res
}
#[instrument( #[instrument(
level = "info", level = "info",
name = "unix_group_token_read", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalunixgrouptokenread( pub async fn handle_internalunixgrouptokenread(
@ -635,9 +582,6 @@ impl QueryServerReadV1 {
) -> Result<UnixGroupToken, OperationError> { ) -> Result<UnixGroupToken, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_read = self.idms.proxy_read_async().await; let mut idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!(
"actors::v1_read::handle<InternalUnixGroupTokenReadMessage>",
{
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -670,14 +614,10 @@ impl QueryServerReadV1 {
idms_prox_read.get_unixgrouptoken(&rate) idms_prox_read.get_unixgrouptoken(&rate)
} }
);
res
}
#[instrument( #[instrument(
level = "info", level = "info",
name = "ssh_key_read", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalsshkeyread( pub async fn handle_internalsshkeyread(
@ -688,7 +628,6 @@ impl QueryServerReadV1 {
) -> Result<Vec<String>, OperationError> { ) -> Result<Vec<String>, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<InternalSshKeyReadMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -736,14 +675,11 @@ impl QueryServerReadV1 {
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "ssh_key_tag_read", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalsshkeytagread( pub async fn handle_internalsshkeytagread(
@ -755,7 +691,6 @@ impl QueryServerReadV1 {
) -> Result<Option<String>, OperationError> { ) -> Result<Option<String>, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<InternalSshKeyTagReadMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -805,14 +740,11 @@ impl QueryServerReadV1 {
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "service_account_api_token_get", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_service_account_api_token_get( pub async fn handle_service_account_api_token_get(
@ -844,8 +776,7 @@ impl QueryServerReadV1 {
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_account_unix_auth", skip_all,
skip(self, uat, uuid_or_name, cred, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmaccountunixauth( pub async fn handle_idmaccountunixauth(
@ -857,7 +788,6 @@ impl QueryServerReadV1 {
) -> Result<Option<UnixUserToken>, OperationError> { ) -> Result<Option<UnixUserToken>, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idm_auth = self.idms.auth_async().await; let mut idm_auth = self.idms.auth_async().await;
// let res = spanned!("actors::v1_read::handle<IdmAccountUnixAuthMessage>", {
// resolve the id // resolve the id
let ident = idm_auth let ident = idm_auth
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -891,14 +821,12 @@ impl QueryServerReadV1 {
security_info!(?res, "Sending result"); security_info!(?res, "Sending result");
// res });
res res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_status", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialstatus( pub async fn handle_idmcredentialstatus(
@ -910,7 +838,6 @@ impl QueryServerReadV1 {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_read = self.idms.proxy_read_async().await; let mut idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<IdmCredentialStatusMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -941,14 +868,11 @@ impl QueryServerReadV1 {
trace!(?cse, "Begin event"); trace!(?cse, "Begin event");
idms_prox_read.get_credentialstatus(&cse) idms_prox_read.get_credentialstatus(&cse)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_backup_code_view", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmbackupcodeview( pub async fn handle_idmbackupcodeview(
@ -960,7 +884,6 @@ impl QueryServerReadV1 {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_read = self.idms.proxy_read_async().await; let mut idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<IdmBackupCodeViewMessage>", {
let ident = idms_prox_read let ident = idms_prox_read
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -991,14 +914,11 @@ impl QueryServerReadV1 {
trace!(?rbce, "Begin event"); trace!(?rbce, "Begin event");
idms_prox_read.get_backup_codes(&rbce) idms_prox_read.get_backup_codes(&rbce)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_update_status", skip_all,
skip(self, session_token, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialupdatestatus( pub async fn handle_idmcredentialupdatestatus(
@ -1008,7 +928,6 @@ impl QueryServerReadV1 {
) -> Result<CUStatus, OperationError> { ) -> Result<CUStatus, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_cred_update = self.idms.cred_update_transaction_async().await; let idms_cred_update = self.idms.cred_update_transaction_async().await;
let res = spanned!("actors::v1_read::handle<IdmCredentialUpdateStatus>", {
let session_token = CredentialUpdateSessionToken { let session_token = CredentialUpdateSessionToken {
token_enc: session_token.token, token_enc: session_token.token,
}; };
@ -1023,14 +942,11 @@ impl QueryServerReadV1 {
e e
}) })
.map(|sta| sta.into()) .map(|sta| sta.into())
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_update", skip_all,
skip(self, session_token, scr, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialupdate( pub async fn handle_idmcredentialupdate(
@ -1041,7 +957,6 @@ impl QueryServerReadV1 {
) -> Result<CUStatus, OperationError> { ) -> Result<CUStatus, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_cred_update = self.idms.cred_update_transaction_async().await; let idms_cred_update = self.idms.cred_update_transaction_async().await;
let res = spanned!("actors::v1_read::handle<IdmCredentialUpdate>", {
let session_token = CredentialUpdateSessionToken { let session_token = CredentialUpdateSessionToken {
token_enc: session_token.token, token_enc: session_token.token,
}; };
@ -1159,14 +1074,11 @@ impl QueryServerReadV1 {
}), }),
} }
.map(|sta| sta.into()) .map(|sta| sta.into())
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_authorise", skip_all,
skip(self, uat, auth_req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_authorise( pub async fn handle_oauth2_authorise(
@ -1177,7 +1089,6 @@ impl QueryServerReadV1 {
) -> Result<AuthoriseResponse, Oauth2Error> { ) -> Result<AuthoriseResponse, Oauth2Error> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<Oauth2Authorise>", {
let (ident, uat) = idms_prox_read let (ident, uat) = idms_prox_read
.validate_and_parse_uat(uat.as_deref(), ct) .validate_and_parse_uat(uat.as_deref(), ct)
.and_then(|uat| { .and_then(|uat| {
@ -1192,14 +1103,11 @@ impl QueryServerReadV1 {
// Now we can send to the idm server for authorisation checking. // Now we can send to the idm server for authorisation checking.
idms_prox_read.check_oauth2_authorisation(&ident, &uat, &auth_req, ct) idms_prox_read.check_oauth2_authorisation(&ident, &uat, &auth_req, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_authorise_permit", skip_all,
skip(self, uat, consent_req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_authorise_permit( pub async fn handle_oauth2_authorise_permit(
@ -1210,7 +1118,6 @@ impl QueryServerReadV1 {
) -> Result<AuthorisePermitSuccess, OperationError> { ) -> Result<AuthorisePermitSuccess, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<Oauth2AuthorisePermit>", {
let (ident, uat) = idms_prox_read let (ident, uat) = idms_prox_read
.validate_and_parse_uat(uat.as_deref(), ct) .validate_and_parse_uat(uat.as_deref(), ct)
.and_then(|uat| { .and_then(|uat| {
@ -1224,14 +1131,11 @@ impl QueryServerReadV1 {
})?; })?;
idms_prox_read.check_oauth2_authorise_permit(&ident, &uat, &consent_req, ct) idms_prox_read.check_oauth2_authorise_permit(&ident, &uat, &consent_req, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_authorise_reject", skip_all,
skip(self, uat, consent_req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_authorise_reject( pub async fn handle_oauth2_authorise_reject(
@ -1242,7 +1146,6 @@ impl QueryServerReadV1 {
) -> Result<Url, OperationError> { ) -> Result<Url, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<Oauth2AuthoriseReject>", {
let (ident, uat) = idms_prox_read let (ident, uat) = idms_prox_read
.validate_and_parse_uat(uat.as_deref(), ct) .validate_and_parse_uat(uat.as_deref(), ct)
.and_then(|uat| { .and_then(|uat| {
@ -1256,14 +1159,11 @@ impl QueryServerReadV1 {
})?; })?;
idms_prox_read.check_oauth2_authorise_reject(&ident, &uat, &consent_req, ct) idms_prox_read.check_oauth2_authorise_reject(&ident, &uat, &consent_req, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_token_exchange", skip_all,
skip(self, client_authz, token_req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_token_exchange( pub async fn handle_oauth2_token_exchange(
@ -1274,17 +1174,13 @@ impl QueryServerReadV1 {
) -> Result<AccessTokenResponse, Oauth2Error> { ) -> Result<AccessTokenResponse, Oauth2Error> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; 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. // 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) idms_prox_read.check_oauth2_token_exchange(client_authz.as_deref(), &token_req, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_token_introspect", skip_all,
skip(self, client_authz, intr_req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_token_introspect( pub async fn handle_oauth2_token_introspect(
@ -1295,17 +1191,13 @@ impl QueryServerReadV1 {
) -> Result<AccessTokenIntrospectResponse, Oauth2Error> { ) -> Result<AccessTokenIntrospectResponse, Oauth2Error> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; 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. // Now we can send to the idm server for introspection checking.
idms_prox_read.check_oauth2_token_introspect(&client_authz, &intr_req, ct) idms_prox_read.check_oauth2_token_introspect(&client_authz, &intr_req, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_openid_userinfo", skip_all,
skip(self, client_id, client_authz, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_openid_userinfo( pub async fn handle_oauth2_openid_userinfo(
@ -1316,16 +1208,12 @@ impl QueryServerReadV1 {
) -> Result<OidcToken, Oauth2Error> { ) -> Result<OidcToken, Oauth2Error> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; 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) idms_prox_read.oauth2_openid_userinfo(&client_id, &client_authz, ct)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_openid_discovery", skip_all,
skip(self, client_id, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_openid_discovery( pub async fn handle_oauth2_openid_discovery(
@ -1334,16 +1222,12 @@ impl QueryServerReadV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<OidcDiscoveryResponse, OperationError> { ) -> Result<OidcDiscoveryResponse, OperationError> {
let idms_prox_read = self.idms.proxy_read_async().await; 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) idms_prox_read.oauth2_openid_discovery(&client_id)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_openid_publickey", skip_all,
skip(self, client_id, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_openid_publickey( pub async fn handle_oauth2_openid_publickey(
@ -1352,30 +1236,22 @@ impl QueryServerReadV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<JwkKeySet, OperationError> { ) -> Result<JwkKeySet, OperationError> {
let idms_prox_read = self.idms.proxy_read_async().await; 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) idms_prox_read.oauth2_openid_publickey(&client_id)
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "get_domain_display_name", skip_all,
skip(self, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn get_domain_display_name(&self, eventid: Uuid) -> String { pub async fn get_domain_display_name(&self, eventid: Uuid) -> String {
let idms_prox_read = self.idms.proxy_read_async().await; 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() idms_prox_read.qs_read.get_domain_display_name().to_string()
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "auth_valid", skip_all,
skip(self, uat, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_auth_valid( pub async fn handle_auth_valid(
@ -1386,7 +1262,6 @@ impl QueryServerReadV1 {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_read = self.idms.proxy_read_async().await; let idms_prox_read = self.idms.proxy_read_async().await;
let res = spanned!("actors::v1_read::handle<AuthValid>", {
idms_prox_read idms_prox_read
.validate_and_parse_uat(uat.as_deref(), ct) .validate_and_parse_uat(uat.as_deref(), ct)
.map(|_| ()) .map(|_| ())
@ -1394,14 +1269,11 @@ impl QueryServerReadV1 {
admin_error!("Invalid token: {:?}", e); admin_error!("Invalid token: {:?}", e);
e e
}) })
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "ldap_request", skip_all,
skip(self, eventid, protomsg, uat)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_ldaprequest( pub async fn handle_ldaprequest(
@ -1410,7 +1282,6 @@ impl QueryServerReadV1 {
protomsg: LdapMsg, protomsg: LdapMsg,
uat: Option<LdapBoundToken>, uat: Option<LdapBoundToken>,
) -> Option<LdapResponseState> { ) -> Option<LdapResponseState> {
// let res = spanned!( "actors::v1_read::handle<LdapRequestMessage>", {
let res = match ServerOps::try_from(protomsg) { let res = match ServerOps::try_from(protomsg) {
Ok(server_op) => self Ok(server_op) => self
.ldap .ldap
@ -1428,7 +1299,6 @@ impl QueryServerReadV1 {
format!("Invalid Request {:?}", &eventid).as_str(), format!("Invalid Request {:?}", &eventid).as_str(),
)), )),
}; };
// });
Some(res) Some(res)
} }
} }

View file

@ -1,43 +1,35 @@
use std::iter; use std::iter;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tracing::{info, instrument, span, trace, Level};
use crate::prelude::*; use kanidm_proto::v1::{
AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest,
use crate::idm::credupdatesession::{ Entry as ProtoEntry, GroupUnixExtend, Modify as ProtoModify, ModifyList as ProtoModifyList,
CredentialUpdateIntentToken, CredentialUpdateSessionToken, InitCredentialUpdateEvent, ModifyRequest, OperationError,
InitCredentialUpdateIntentEvent,
}; };
use time::OffsetDateTime;
use tracing::{info, instrument, span, trace, Level};
use uuid::Uuid;
use crate::event::{ use crate::event::{
CreateEvent, DeleteEvent, ModifyEvent, PurgeRecycledEvent, PurgeTombstoneEvent, CreateEvent, DeleteEvent, ModifyEvent, PurgeRecycledEvent, PurgeTombstoneEvent,
ReviveRecycledEvent, ReviveRecycledEvent,
}; };
use crate::filter::{Filter, FilterInvalid};
use crate::idm::credupdatesession::{
CredentialUpdateIntentToken, CredentialUpdateSessionToken, InitCredentialUpdateEvent,
InitCredentialUpdateIntentEvent,
};
use crate::idm::delayed::DelayedAction;
use crate::idm::event::{ use crate::idm::event::{
GeneratePasswordEvent, RegenerateRadiusSecretEvent, UnixPasswordChangeEvent, 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::server::{IdmServer, IdmServerTransaction};
use crate::idm::serviceaccount::{DestroyApiTokenEvent, GenerateApiTokenEvent}; use crate::idm::serviceaccount::{DestroyApiTokenEvent, GenerateApiTokenEvent};
use crate::modify::{Modify, ModifyInvalid, ModifyList};
use crate::prelude::*;
use crate::utils::duration_from_epoch_now; use crate::utils::duration_from_epoch_now;
use crate::value::{PartialValue, Value};
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;
pub struct QueryServerWriteV1 { pub struct QueryServerWriteV1 {
_log_level: Option<u32>, _log_level: Option<u32>,
@ -63,6 +55,7 @@ impl QueryServerWriteV1 {
&(*x_ptr) &(*x_ptr)
} }
#[instrument(level = "debug", skip_all)]
async fn modify_from_parts( async fn modify_from_parts(
&self, &self,
uat: Option<String>, uat: Option<String>,
@ -71,7 +64,6 @@ impl QueryServerWriteV1 {
filter: Filter<FilterInvalid>, filter: Filter<FilterInvalid>,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
@ -109,9 +101,9 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
})
} }
#[instrument(level = "debug", skip_all)]
async fn modify_from_internal_parts( async fn modify_from_internal_parts(
&self, &self,
uat: Option<String>, uat: Option<String>,
@ -120,7 +112,6 @@ impl QueryServerWriteV1 {
filter: Filter<FilterInvalid>, filter: Filter<FilterInvalid>,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
@ -161,13 +152,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
})
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "create", skip_all,
skip(self, uat, req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_create( pub async fn handle_create(
@ -177,7 +166,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
@ -201,15 +189,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.create(&crt) .create(&crt)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
});
// At the end of the event we send it for logging.
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "modify", skip_all,
skip(self, uat, req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_modify( pub async fn handle_modify(
@ -219,7 +203,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -242,14 +225,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "delete", skip_all,
skip(self, uat, req, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_delete( pub async fn handle_delete(
@ -259,7 +239,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -281,14 +260,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.delete(&del) .delete(&del)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "patch", skip_all,
skip(self, uat, filter, update, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internalpatch( pub async fn handle_internalpatch(
@ -300,7 +276,6 @@ impl QueryServerWriteV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
// Given a protoEntry, turn this into a modification set. // Given a protoEntry, turn this into a modification set.
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -310,18 +285,13 @@ impl QueryServerWriteV1 {
})?; })?;
// Transform the ProtoEntry to a Modlist // Transform the ProtoEntry to a Modlist
let modlist = let modlist = ModifyList::from_patch(&update, &idms_prox_write.qs_write).map_err(|e| {
ModifyList::from_patch(&update, &idms_prox_write.qs_write).map_err(|e| {
admin_error!(err = ?e, "Invalid Patch Request"); admin_error!(err = ?e, "Invalid Patch Request");
e e
})?; })?;
let mdf = ModifyEvent::from_internal_parts( let mdf =
ident, ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write)
&modlist,
&filter,
&idms_prox_write.qs_write,
)
.map_err(|e| { .map_err(|e| {
admin_error!(err = ?e, "Failed to begin modify"); admin_error!(err = ?e, "Failed to begin modify");
e e
@ -333,14 +303,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
});
res.map(|_| ())
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "delete2", skip_all,
skip(self, uat, filter, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_internaldelete( pub async fn handle_internaldelete(
@ -350,7 +317,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -372,14 +338,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.delete(&del) .delete(&del)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "revive_recycled", skip_all,
skip(self, uat, filter, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_reviverecycled( pub async fn handle_reviverecycled(
@ -389,7 +352,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -397,8 +359,7 @@ impl QueryServerWriteV1 {
admin_error!(err = ?e, "Invalid identity"); admin_error!(err = ?e, "Invalid identity");
e e
})?; })?;
let rev = let rev = match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) {
match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
admin_error!(err = ?e, "Failed to begin revive"); admin_error!(err = ?e, "Failed to begin revive");
@ -412,14 +373,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.revive_recycled(&rev) .revive_recycled(&rev)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "service_account_credential_generate", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_service_account_credential_generate( pub async fn handle_service_account_credential_generate(
@ -430,7 +388,6 @@ impl QueryServerWriteV1 {
) -> Result<String, OperationError> { ) -> Result<String, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; 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 let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -461,14 +418,11 @@ impl QueryServerWriteV1 {
idms_prox_write idms_prox_write
.generate_account_password(&gpe) .generate_account_password(&gpe)
.and_then(|r| idms_prox_write.commit().map(|_| r)) .and_then(|r| idms_prox_write.commit().map(|_| r))
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "service_account_credential_generate", skip_all,
skip(self, uat, uuid_or_name, label, expiry, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_service_account_api_token_generate( pub async fn handle_service_account_api_token_generate(
@ -510,7 +464,6 @@ impl QueryServerWriteV1 {
#[instrument( #[instrument(
level = "info", level = "info",
name = "service_account_credential_generate",
skip_all, skip_all,
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
@ -551,8 +504,7 @@ impl QueryServerWriteV1 {
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_update", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialupdate( pub async fn handle_idmcredentialupdate(
@ -563,7 +515,6 @@ impl QueryServerWriteV1 {
) -> Result<(CUSessionToken, CUStatus), OperationError> { ) -> Result<(CUSessionToken, CUStatus), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; 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 let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -597,14 +548,11 @@ impl QueryServerWriteV1 {
sta.into(), sta.into(),
) )
}) })
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_update_intent", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialupdateintent( pub async fn handle_idmcredentialupdateintent(
@ -616,7 +564,6 @@ impl QueryServerWriteV1 {
) -> Result<CUIntentToken, OperationError> { ) -> Result<CUIntentToken, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; 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 let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -648,14 +595,11 @@ impl QueryServerWriteV1 {
.map(|tok| CUIntentToken { .map(|tok| CUIntentToken {
token: tok.intent_id, token: tok.intent_id,
}) })
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_exchange_intent", skip_all,
skip(self, intent_token, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialexchangeintent( pub async fn handle_idmcredentialexchangeintent(
@ -665,7 +609,6 @@ impl QueryServerWriteV1 {
) -> Result<(CUSessionToken, CUStatus), OperationError> { ) -> Result<(CUSessionToken, CUStatus), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
let res = spanned!("actors::v1_write::handle<IdmCredentialExchangeIntent>", {
let intent_token = CredentialUpdateIntentToken { let intent_token = CredentialUpdateIntentToken {
intent_id: intent_token.token, intent_id: intent_token.token,
}; };
@ -688,14 +631,11 @@ impl QueryServerWriteV1 {
sta.into(), sta.into(),
) )
}) })
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_update_commit", skip_all,
skip(self, session_token, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialupdatecommit( pub async fn handle_idmcredentialupdatecommit(
@ -705,7 +645,6 @@ impl QueryServerWriteV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
let res = spanned!("actors::v1_write::handle<IdmCredentialUpdateCommit>", {
let session_token = CredentialUpdateSessionToken { let session_token = CredentialUpdateSessionToken {
token_enc: session_token.token, token_enc: session_token.token,
}; };
@ -720,14 +659,11 @@ impl QueryServerWriteV1 {
); );
e e
}) })
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_credential_update_cancel", skip_all,
skip(self, session_token, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmcredentialupdatecancel( pub async fn handle_idmcredentialupdatecancel(
@ -737,7 +673,6 @@ impl QueryServerWriteV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; let mut idms_prox_write = self.idms.proxy_write_async(ct).await;
let res = spanned!("actors::v1_write::handle<IdmCredentialUpdateCancel>", {
let session_token = CredentialUpdateSessionToken { let session_token = CredentialUpdateSessionToken {
token_enc: session_token.token, token_enc: session_token.token,
}; };
@ -752,14 +687,11 @@ impl QueryServerWriteV1 {
); );
e e
}) })
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "handle_service_account_into_person", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_service_account_into_person( pub async fn handle_service_account_into_person(
@ -770,7 +702,6 @@ impl QueryServerWriteV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_write = self.idms.proxy_write_async(ct).await; let idms_prox_write = self.idms.proxy_write_async(ct).await;
let res = spanned!("actors::v1_write::handle<IdmServiceAccountIntoPerson>", {
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -788,14 +719,11 @@ impl QueryServerWriteV1 {
idms_prox_write idms_prox_write
.service_account_into_person(&ident, target_uuid) .service_account_into_person(&ident, target_uuid)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "regenerate_radius_secret", skip_all,
skip(self, uat, uuid_or_name, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_regenerateradius( pub async fn handle_regenerateradius(
@ -806,9 +734,6 @@ impl QueryServerWriteV1 {
) -> Result<String, OperationError> { ) -> Result<String, OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; 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 let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -841,14 +766,10 @@ impl QueryServerWriteV1 {
.regenerate_radius_secret(&rrse) .regenerate_radius_secret(&rrse)
.and_then(|r| idms_prox_write.commit().map(|_| r)) .and_then(|r| idms_prox_write.commit().map(|_| r))
} }
);
res
}
#[instrument( #[instrument(
level = "info", level = "info",
name = "purge_attribute", skip_all,
skip(self, uat, uuid_or_name, attr, filter, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_purgeattribute( pub async fn handle_purgeattribute(
@ -861,7 +782,6 @@ impl QueryServerWriteV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idms_prox_write = self.idms.proxy_write_async(ct).await; let idms_prox_write = self.idms.proxy_write_async(ct).await;
spanned!("actors::v1_write::handle<PurgeAttributeMessage>", {
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -896,13 +816,11 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
})
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "remove_attribute_values", skip_all,
skip(self, uat, uuid_or_name, attr, values, filter, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_removeattributevalues( pub async fn handle_removeattributevalues(
@ -915,7 +833,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
@ -958,7 +875,6 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
})
} }
#[instrument( #[instrument(
@ -1121,8 +1037,7 @@ impl QueryServerWriteV1 {
#[instrument( #[instrument(
level = "info", level = "info",
name = "idm_account_unix_set_cred", skip_all,
skip(self, uat, uuid_or_name, cred, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_idmaccountunixsetcred( pub async fn handle_idmaccountunixsetcred(
@ -1134,7 +1049,6 @@ impl QueryServerWriteV1 {
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; 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 let ident = idms_prox_write
.validate_and_parse_token_to_ident(uat.as_deref(), ct) .validate_and_parse_token_to_ident(uat.as_deref(), ct)
.map_err(|e| { .map_err(|e| {
@ -1166,14 +1080,11 @@ impl QueryServerWriteV1 {
.set_unix_account_password(&upce) .set_unix_account_password(&upce)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
.map(|_| ()) .map(|_| ())
});
res
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_scopemap_create", skip_all,
skip(self, uat, filter, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_scopemap_create( 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 // Because this is from internal, we can generate a real modlist, rather
// than relying on the proto ones. // than relying on the proto ones.
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
@ -1208,11 +1118,7 @@ impl QueryServerWriteV1 {
let ml = ModifyList::new_append( let ml = ModifyList::new_append(
"oauth2_rs_scope_map", "oauth2_rs_scope_map",
Value::new_oauthscopemap(group_uuid, scopes.into_iter().collect()).ok_or_else( 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 .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
})
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "oauth2_scopemap_delete", skip_all,
skip(self, uat, filter, eventid)
fields(uuid = ?eventid) fields(uuid = ?eventid)
)] )]
pub async fn handle_oauth2_scopemap_delete( pub async fn handle_oauth2_scopemap_delete(
@ -1252,7 +1156,6 @@ impl QueryServerWriteV1 {
eventid: Uuid, eventid: Uuid,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 ct = duration_from_epoch_now();
let ident = idms_prox_write let ident = idms_prox_write
@ -1291,21 +1194,18 @@ impl QueryServerWriteV1 {
.qs_write .qs_write
.modify(&mdf) .modify(&mdf)
.and_then(|_| idms_prox_write.commit().map(|_| ())) .and_then(|_| idms_prox_write.commit().map(|_| ()))
})
} }
// ===== These below are internal only event types. ===== // ===== These below are internal only event types. =====
#[instrument( #[instrument(
level = "info", level = "info",
name = "purge_tombstone_event", skip_all,
skip(self, msg)
fields(uuid = ?msg.eventid) fields(uuid = ?msg.eventid)
)] )]
pub(crate) async fn handle_purgetombstoneevent(&self, msg: PurgeTombstoneEvent) { pub(crate) async fn handle_purgetombstoneevent(&self, msg: PurgeTombstoneEvent) {
trace!(?msg, "Begin purge tombstone event"); trace!(?msg, "Begin purge tombstone event");
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 let res = idms_prox_write
.qs_write .qs_write
.purge_tombstones() .purge_tombstones()
@ -1313,19 +1213,16 @@ impl QueryServerWriteV1 {
admin_info!(?res, "Purge tombstones result"); admin_info!(?res, "Purge tombstones result");
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
res.expect("Invalid Server State"); res.expect("Invalid Server State");
});
} }
#[instrument( #[instrument(
level = "info", level = "info",
name = "purge_recycled_event", skip_all,
skip(self, msg)
fields(uuid = ?msg.eventid) fields(uuid = ?msg.eventid)
)] )]
pub(crate) async fn handle_purgerecycledevent(&self, msg: PurgeRecycledEvent) { pub(crate) async fn handle_purgerecycledevent(&self, msg: PurgeRecycledEvent) {
trace!(?msg, "Begin purge recycled event"); trace!(?msg, "Begin purge recycled event");
let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; 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 let res = idms_prox_write
.qs_write .qs_write
.purge_recycled() .purge_recycled()
@ -1333,7 +1230,6 @@ impl QueryServerWriteV1 {
admin_info!(?res, "Purge recycled result"); admin_info!(?res, "Purge recycled result");
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
res.expect("Invalid Server State"); res.expect("Invalid Server State");
});
} }
pub(crate) async fn handle_delayedaction(&self, da: DelayedAction) { pub(crate) async fn handle_delayedaction(&self, da: DelayedAction) {
@ -1344,13 +1240,11 @@ impl QueryServerWriteV1 {
trace!("Begin delayed action ..."); trace!("Begin delayed action ...");
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let mut idms_prox_write = self.idms.proxy_write_async(ct).await; 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 if let Err(res) = idms_prox_write
.process_delayedaction(da) .process_delayedaction(da)
.and_then(|_| idms_prox_write.commit()) .and_then(|_| idms_prox_write.commit())
{ {
admin_info!(?res, "delayed action error"); admin_info!(?res, "delayed action error");
} }
});
} }
} }

View file

@ -1,6 +1,7 @@
use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use serde::{Deserialize, Serialize};
include!("./audit_loglevel.rs"); include!("./audit_loglevel.rs");
pub const AUDIT_LINE_SIZE: usize = 512; pub const AUDIT_LINE_SIZE: usize = 512;

View file

@ -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::collections::BTreeMap;
use std::time::Duration; use std::time::Duration;
use serde::{Deserialize, Serialize};
use smartstring::alias::String as AttrString;
use uuid::Uuid; use uuid::Uuid;
use crate::be::dbvalue::{DbValueEmailAddressV1, DbValuePhoneNumberV1, DbValueSetV2, DbValueV1};
use crate::prelude::OperationError;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct DbEntryV1 { pub struct DbEntryV1 {
pub attrs: BTreeMap<AttrString, Vec<DbValueV1>>, pub attrs: BTreeMap<AttrString, Vec<DbValueV1>>,

View file

@ -1,15 +1,15 @@
use hashbrown::HashSet;
use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::time::Duration; use std::time::Duration;
use hashbrown::HashSet;
use serde::{Deserialize, Serialize};
use url::Url; use url::Url;
use uuid::Uuid; 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_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)] #[derive(Serialize, Deserialize, Debug)]
pub struct DbCidV1 { pub struct DbCidV1 {
#[serde(rename = "d")] #[serde(rename = "d")]
@ -556,11 +556,11 @@ impl DbValueSetV2 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::DbCred;
use super::{DbBackupCodeV1, DbPasswordV1, DbTotpV1, DbWebauthnV1};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use super::{DbBackupCodeV1, DbCred, DbPasswordV1, DbTotpV1, DbWebauthnV1};
fn dbcred_type_default_pw() -> DbCredTypeV1 { fn dbcred_type_default_pw() -> DbCredTypeV1 {
DbCredTypeV1::Pw DbCredTypeV1::Pw
} }

View file

@ -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::{ use crate::be::idl_sqlite::{
IdlSqlite, IdlSqliteReadTransaction, IdlSqliteTransaction, IdlSqliteWriteTransaction, IdlSqlite, IdlSqliteReadTransaction, IdlSqliteTransaction, IdlSqliteWriteTransaction,
}; };
@ -6,24 +21,8 @@ use crate::be::idxkey::{
}; };
use crate::be::{BackendConfig, IdList, IdRawEntry}; use crate::be::{BackendConfig, IdList, IdRawEntry};
use crate::entry::{Entry, EntryCommitted, EntrySealed}; 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 crate::prelude::*;
use tracing::trace; use crate::value::{IndexType, Value};
// use std::borrow::Borrow; // use std::borrow::Borrow;
@ -82,7 +81,6 @@ macro_rules! get_identry {
$idl:expr, $idl:expr,
$is_read_op:expr $is_read_op:expr
) => {{ ) => {{
spanned!("be::idl_arc_sqlite::get_identry", {
let mut result: Vec<Arc<EntrySealedCommitted>> = Vec::new(); let mut result: Vec<Arc<EntrySealedCommitted>> = Vec::new();
match $idl { match $idl {
IdList::Partial(idli) | IdList::PartialThreshold(idli) | IdList::Indexed(idli) => { IdList::Partial(idli) | IdList::PartialThreshold(idli) | IdList::Indexed(idli) => {
@ -133,7 +131,6 @@ macro_rules! get_identry {
}; };
// Return // Return
Ok(result) Ok(result)
})
}}; }};
} }
@ -165,7 +162,6 @@ macro_rules! get_idl {
$itype:expr, $itype:expr,
$idx_key:expr $idx_key:expr
) => {{ ) => {{
spanned!("be::idl_arc_sqlite::get_idl", {
// SEE ALSO #259: Find a way to implement borrow for this properly. // 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 // 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 // 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 hit, continue.
if let Some(ref data) = cache_r { if let Some(ref data) = cache_r {
trace!( trace!(
%data, cached_index = ?$itype,
"Got cached idl for index {:?} {:?}", attr = ?$attr,
$itype, idl = %data,
$attr,
); );
return Ok(Some(data.as_ref().clone())); 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())) $self.idl_cache.insert(ncache_key, Box::new(idl.clone()))
} }
Ok(db_r) Ok(db_r)
})
}}; }};
} }
@ -215,7 +209,6 @@ macro_rules! name2uuid {
$self:expr, $self:expr,
$name:expr $name:expr
) => {{ ) => {{
spanned!("be::idl_arc_sqlite::name2uuid", {
let cache_key = NameCacheKey::Name2Uuid($name.to_string()); let cache_key = NameCacheKey::Name2Uuid($name.to_string());
let cache_r = $self.name_cache.get(&cache_key); let cache_r = $self.name_cache.get(&cache_key);
if let Some(NameCacheValue::U(uuid)) = cache_r { if let Some(NameCacheValue::U(uuid)) = cache_r {
@ -232,7 +225,6 @@ macro_rules! name2uuid {
.insert(cache_key, NameCacheValue::U(uuid.clone())) .insert(cache_key, NameCacheValue::U(uuid.clone()))
} }
Ok(db_r) Ok(db_r)
})
}}; }};
} }
@ -241,7 +233,6 @@ macro_rules! uuid2spn {
$self:expr, $self:expr,
$uuid:expr $uuid:expr
) => {{ ) => {{
spanned!("be::idl_arc_sqlite::uuid2spn", {
let cache_key = NameCacheKey::Uuid2Spn($uuid); let cache_key = NameCacheKey::Uuid2Spn($uuid);
let cache_r = $self.name_cache.get(&cache_key); let cache_r = $self.name_cache.get(&cache_key);
if let Some(NameCacheValue::S(ref spn)) = cache_r { 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()))) .insert(cache_key, NameCacheValue::S(Box::new(data.clone())))
} }
Ok(db_r) Ok(db_r)
})
}}; }};
} }
@ -267,7 +257,6 @@ macro_rules! uuid2rdn {
$self:expr, $self:expr,
$uuid:expr $uuid:expr
) => {{ ) => {{
spanned!("be::idl_arc_sqlite::uuid2rdn", {
let cache_key = NameCacheKey::Uuid2Rdn($uuid); let cache_key = NameCacheKey::Uuid2Rdn($uuid);
let cache_r = $self.name_cache.get(&cache_key); let cache_r = $self.name_cache.get(&cache_key);
if let Some(NameCacheValue::R(ref rdn)) = cache_r { if let Some(NameCacheValue::R(ref rdn)) = cache_r {
@ -283,7 +272,6 @@ macro_rules! uuid2rdn {
.insert(cache_key, NameCacheValue::R(data.clone())) .insert(cache_key, NameCacheValue::R(data.clone()))
} }
Ok(db_r) Ok(db_r)
})
}}; }};
} }
@ -528,8 +516,8 @@ impl<'a> IdlArcSqliteTransaction for IdlArcSqliteWriteTransaction<'a> {
} }
impl<'a> IdlArcSqliteWriteTransaction<'a> { impl<'a> IdlArcSqliteWriteTransaction<'a> {
#[instrument(level = "debug", name = "idl_arc_sqlite::commit", skip_all)]
pub fn commit(self) -> Result<(), OperationError> { pub fn commit(self) -> Result<(), OperationError> {
spanned!("be::idl_arc_sqlite::commit", {
let IdlArcSqliteWriteTransaction { let IdlArcSqliteWriteTransaction {
db, db,
mut entry_cache, mut entry_cache,
@ -541,21 +529,20 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
} = self; } = self;
// Write any dirty items to the disk. // Write any dirty items to the disk.
spanned!("be::idl_arc_sqlite::commit<entry>", {
entry_cache entry_cache
.iter_mut_mark_clean() .iter_mut_mark_clean()
.try_for_each(|(k, v)| match v { .try_for_each(|(k, v)| match v {
Some(e) => db.write_identry(e), Some(e) => db.write_identry(e),
None => db.delete_identry(*k), None => db.delete_identry(*k),
}) })
})
.map_err(|e| { .map_err(|e| {
admin_error!(?e, "Failed to sync entry cache to sqlite"); admin_error!(?e, "Failed to sync entry cache to sqlite");
e e
})?; })?;
spanned!("be::idl_arc_sqlite::commit<idl>", { idl_cache
idl_cache.iter_mut_mark_clean().try_for_each(|(k, v)| { .iter_mut_mark_clean()
.try_for_each(|(k, v)| {
match v { match v {
Some(idl) => db.write_idl(k.a.as_str(), k.i, k.k.as_str(), idl), Some(idl) => db.write_idl(k.a.as_str(), k.i, k.k.as_str(), idl),
#[allow(clippy::unreachable)] #[allow(clippy::unreachable)]
@ -570,13 +557,11 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
} }
} }
}) })
})
.map_err(|e| { .map_err(|e| {
admin_error!(?e, "Failed to sync idl cache to sqlite"); admin_error!(?e, "Failed to sync idl cache to sqlite");
e e
})?; })?;
spanned!("be::idl_arc_sqlite::commit<names>", {
name_cache name_cache
.iter_mut_mark_clean() .iter_mut_mark_clean()
.try_for_each(|(k, v)| match (k, v) { .try_for_each(|(k, v)| match (k, v) {
@ -595,7 +580,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
_ => Err(OperationError::InvalidCacheState), _ => Err(OperationError::InvalidCacheState),
}) })
})
.map_err(|e| { .map_err(|e| {
admin_error!(?e, "Failed to sync name cache to sqlite"); admin_error!(?e, "Failed to sync name cache to sqlite");
e e
@ -610,7 +594,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
allids.commit(); allids.commit();
maxid.commit(); maxid.commit();
}) })
})
} }
pub fn get_id2entry_max_id(&self) -> Result<u64, OperationError> { pub fn get_id2entry_max_id(&self) -> Result<u64, OperationError> {
@ -626,7 +609,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
where where
I: Iterator<Item = &'b Entry<EntrySealed, EntryCommitted>>, I: Iterator<Item = &'b Entry<EntrySealed, EntryCommitted>>,
{ {
spanned!("be::idl_arc_sqlite::write_identries", {
entries.try_for_each(|e| { entries.try_for_each(|e| {
trace!("Inserting {:?} to cache", e.get_id()); trace!("Inserting {:?} to cache", e.get_id());
if e.get_id() == 0 { if e.get_id() == 0 {
@ -638,7 +620,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
Ok(()) Ok(())
} }
}) })
})
} }
pub fn write_identries_raw<I>(&mut self, entries: I) -> Result<(), OperationError> pub fn write_identries_raw<I>(&mut self, entries: I) -> Result<(), OperationError>
@ -661,7 +642,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
where where
I: Iterator<Item = u64>, I: Iterator<Item = u64>,
{ {
spanned!("be::idl_arc_sqlite::delete_identry", {
idl.try_for_each(|i| { idl.try_for_each(|i| {
trace!("Removing {:?} from cache", i); trace!("Removing {:?} from cache", i);
if i == 0 { if i == 0 {
@ -672,7 +652,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
Ok(()) Ok(())
} }
}) })
})
} }
pub fn write_idl( pub fn write_idl(
@ -682,7 +661,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
idx_key: &str, idx_key: &str,
idl: &IDLBitRange, idl: &IDLBitRange,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("be::idl_arc_sqlite::write_idl", {
let cache_key = IdlCacheKey { let cache_key = IdlCacheKey {
a: attr.into(), a: attr.into(),
i: itype, i: itype,
@ -700,14 +678,13 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
} }
// self.db.write_idl(audit, attr, itype, idx_key, idl) // self.db.write_idl(audit, attr, itype, idx_key, idl)
Ok(()) Ok(())
})
} }
pub fn optimise_dirty_idls(&mut self) { pub fn optimise_dirty_idls(&mut self) {
self.idl_cache.iter_mut_dirty().for_each(|(k, maybe_idl)| { self.idl_cache.iter_mut_dirty().for_each(|(k, maybe_idl)| {
if let Some(idl) = maybe_idl { if let Some(idl) = maybe_idl {
if idl.maybe_compress() { if idl.maybe_compress() {
filter_trace!(?k, "Compressed idl"); trace!(?k, "Compressed idl");
} }
} }
}) })
@ -971,27 +948,21 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
uuid: Uuid, uuid: Uuid,
add: BTreeSet<String>, add: BTreeSet<String>,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("be::idl_arc_sqlite::write_name2uuid_add", {
add.into_iter().for_each(|k| { add.into_iter().for_each(|k| {
let cache_key = NameCacheKey::Name2Uuid(k); let cache_key = NameCacheKey::Name2Uuid(k);
let cache_value = NameCacheValue::U(uuid); let cache_value = NameCacheValue::U(uuid);
self.name_cache.insert_dirty(cache_key, cache_value) self.name_cache.insert_dirty(cache_key, cache_value)
}); });
Ok(()) Ok(())
})
} }
pub fn write_name2uuid_rem(&mut self, rem: BTreeSet<String>) -> Result<(), OperationError> { 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| { rem.into_iter().for_each(|k| {
// why not just a for loop here... // why not just a for loop here...
let cache_key = NameCacheKey::Name2Uuid(k); let cache_key = NameCacheKey::Name2Uuid(k);
self.name_cache.remove_dirty(cache_key) self.name_cache.remove_dirty(cache_key)
}); });
Ok(()) Ok(())
// })
})
} }
pub fn create_uuid2spn(&self) -> Result<(), OperationError> { 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> { 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); let cache_key = NameCacheKey::Uuid2Spn(uuid);
match k { match k {
Some(v) => self Some(v) => self
@ -1008,7 +978,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
None => self.name_cache.remove_dirty(cache_key), None => self.name_cache.remove_dirty(cache_key),
} }
Ok(()) Ok(())
})
} }
pub fn create_uuid2rdn(&self) -> Result<(), OperationError> { 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> { 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); let cache_key = NameCacheKey::Uuid2Rdn(uuid);
match k { match k {
Some(s) => self Some(s) => self
@ -1025,7 +993,6 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
None => self.name_cache.remove_dirty(cache_key), None => self.name_cache.remove_dirty(cache_key),
} }
Ok(()) Ok(())
})
} }
pub fn create_idx(&self, attr: &str, itype: IndexType) -> Result<(), OperationError> { pub fn create_idx(&self, attr: &str, itype: IndexType) -> Result<(), OperationError> {

View file

@ -1,24 +1,22 @@
use crate::be::dbentry::DbEntry; use std::convert::{TryFrom, TryInto};
use crate::be::dbentry::DbIdentSpn; use std::sync::Arc;
use crate::be::{BackendConfig, IdList, IdRawEntry, IdxKey, IdxSlope}; use std::time::Duration;
use crate::entry::{Entry, EntryCommitted, EntrySealed};
use crate::prelude::*;
use crate::value::{IndexType, Value};
// use crate::valueset; // use crate::valueset;
use hashbrown::HashMap; use hashbrown::HashMap;
use idlset::v2::IDLBitRange; use idlset::v2::IDLBitRange;
use kanidm_proto::v1::{ConsistencyError, OperationError}; use kanidm_proto::v1::{ConsistencyError, OperationError};
use r2d2::Pool; use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager; use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::Connection; use rusqlite::{Connection, OpenFlags, OptionalExtension};
use rusqlite::OpenFlags;
use rusqlite::OptionalExtension;
use std::convert::{TryFrom, TryInto};
use std::sync::Arc;
use std::time::Duration;
use tracing::trace;
use uuid::Uuid; 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; // use uuid::Uuid;
const DBV_ID2ENTRY: &str = "id2entry"; const DBV_ID2ENTRY: &str = "id2entry";
@ -117,12 +115,10 @@ pub trait IdlSqliteTransaction {
fn get_conn(&self) -> &r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>; fn get_conn(&self) -> &r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
fn get_identry(&self, idl: &IdList) -> Result<Vec<Arc<EntrySealedCommitted>>, OperationError> { fn get_identry(&self, idl: &IdList) -> Result<Vec<Arc<EntrySealedCommitted>>, OperationError> {
spanned!("be::idl_sqlite::get_identry", {
self.get_identry_raw(idl)? self.get_identry_raw(idl)?
.into_iter() .into_iter()
.map(|ide| ide.into_entry().map(Arc::new)) .map(|ide| ide.into_entry().map(Arc::new))
.collect() .collect()
})
} }
fn get_identry_raw(&self, idl: &IdList) -> Result<Vec<IdRawEntry>, OperationError> { fn get_identry_raw(&self, idl: &IdList) -> Result<Vec<IdRawEntry>, OperationError> {
@ -220,7 +216,6 @@ pub trait IdlSqliteTransaction {
itype: IndexType, itype: IndexType,
idx_key: &str, idx_key: &str,
) -> Result<Option<IDLBitRange>, OperationError> { ) -> Result<Option<IDLBitRange>, OperationError> {
spanned!("be::idl_sqlite::get_idl", {
if !(self.exists_idx(attr, itype)?) { if !(self.exists_idx(attr, itype)?) {
filter_error!( filter_error!(
"IdlSqliteTransaction: Index {:?} {:?} not found", "IdlSqliteTransaction: Index {:?} {:?} not found",
@ -252,14 +247,17 @@ pub trait IdlSqliteTransaction {
// have a corrupted index ..... // have a corrupted index .....
None => IDLBitRange::new(), None => IDLBitRange::new(),
}; };
trace!(%idl, "Got idl for index {:?} {:?}", itype, attr);
trace!(
miss_index = ?itype,
attr = ?attr,
idl = %idl,
);
Ok(Some(idl)) Ok(Some(idl))
})
} }
fn name2uuid(&mut self, name: &str) -> Result<Option<Uuid>, OperationError> { 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. // The table exists - lets now get the actual index itself.
let mut stmt = self let mut stmt = self
.get_conn() .get_conn()
@ -272,14 +270,11 @@ pub trait IdlSqliteTransaction {
.map_err(sqlite_error)?; .map_err(sqlite_error)?;
let uuid = uuid_raw.as_ref().and_then(|u| Uuid::parse_str(u).ok()); let uuid = uuid_raw.as_ref().and_then(|u| Uuid::parse_str(u).ok());
trace!(%name, ?uuid, "Got uuid for index");
Ok(uuid) Ok(uuid)
})
} }
fn uuid2spn(&mut self, uuid: Uuid) -> Result<Option<Value>, OperationError> { fn uuid2spn(&mut self, uuid: Uuid) -> Result<Option<Value>, OperationError> {
spanned!("be::idl_sqlite::uuid2spn", {
let uuids = uuid.as_hyphenated().to_string(); let uuids = uuid.as_hyphenated().to_string();
// The table exists - lets now get the actual index itself. // The table exists - lets now get the actual index itself.
let mut stmt = self let mut stmt = self
@ -302,14 +297,10 @@ pub trait IdlSqliteTransaction {
None => None, None => None,
}; };
trace!(?uuid, ?spn, "Got spn for uuid");
Ok(spn) Ok(spn)
})
} }
fn uuid2rdn(&mut self, uuid: Uuid) -> Result<Option<String>, OperationError> { fn uuid2rdn(&mut self, uuid: Uuid) -> Result<Option<String>, OperationError> {
spanned!("be::idl_sqlite::uuid2rdn", {
let uuids = uuid.as_hyphenated().to_string(); let uuids = uuid.as_hyphenated().to_string();
// The table exists - lets now get the actual index itself. // The table exists - lets now get the actual index itself.
let mut stmt = self let mut stmt = self
@ -322,10 +313,7 @@ pub trait IdlSqliteTransaction {
.optional() .optional()
.map_err(sqlite_error)?; .map_err(sqlite_error)?;
trace!(?uuid, ?rdn, "Got rdn for uuid");
Ok(rdn) Ok(rdn)
})
} }
fn get_db_s_uuid(&self) -> Result<Option<Uuid>, OperationError> { 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> { fn get_allids(&self) -> Result<IDLBitRange, OperationError> {
trace!("Building allids...");
let mut stmt = self let mut stmt = self
.get_conn() .get_conn()
.prepare("SELECT id FROM id2entry") .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> { pub fn commit(mut self) -> Result<(), OperationError> {
spanned!("be::idl_sqlite::commit", {
trace!("Commiting BE WR txn");
assert!(!self.committed); assert!(!self.committed);
self.committed = true; self.committed = true;
@ -617,7 +604,6 @@ impl IdlSqliteWriteTransaction {
admin_error!(?e, "CRITICAL: failed to commit sqlite txn"); admin_error!(?e, "CRITICAL: failed to commit sqlite txn");
OperationError::BackendEngine OperationError::BackendEngine
}) })
})
} }
pub fn get_id2entry_max_id(&self) -> Result<u64, OperationError> { pub fn get_id2entry_max_id(&self) -> Result<u64, OperationError> {
@ -770,9 +756,7 @@ impl IdlSqliteWriteTransaction {
idx_key: &str, idx_key: &str,
idl: &IDLBitRange, idl: &IDLBitRange,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("be::idl_sqlite::write_idl", {
if idl.is_empty() { if idl.is_empty() {
trace!(?idl, "purging idl");
// delete it // delete it
// Delete this idx_key from the table. // Delete this idx_key from the table.
let query = format!( let query = format!(
@ -786,7 +770,6 @@ impl IdlSqliteWriteTransaction {
.and_then(|mut stmt| stmt.execute(&[(":key", &idx_key)])) .and_then(|mut stmt| stmt.execute(&[(":key", &idx_key)]))
.map_err(sqlite_error) .map_err(sqlite_error)
} else { } else {
trace!(?idl, "writing idl");
// Serialise the IdList to Vec<u8> // Serialise the IdList to Vec<u8>
let idl_raw = serde_json::to_vec(idl).map_err(serde_json_error)?; 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 // Get rid of the sqlite rows usize
.map(|_| ()) .map(|_| ())
})
} }
pub fn create_name2uuid(&self) -> Result<(), OperationError> { pub fn create_name2uuid(&self) -> Result<(), OperationError> {
@ -944,7 +926,7 @@ impl IdlSqliteWriteTransaction {
itype.as_idx_str(), itype.as_idx_str(),
attr attr
); );
trace!(idx = %idx_stmt, "Creating index"); trace!(idx = %idx_stmt, "creating index");
self.conn self.conn
.execute(idx_stmt.as_str(), []) .execute(idx_stmt.as_str(), [])
@ -1034,7 +1016,6 @@ impl IdlSqliteWriteTransaction {
} }
pub unsafe fn purge_id2entry(&self) -> Result<(), OperationError> { pub unsafe fn purge_id2entry(&self) -> Result<(), OperationError> {
trace!("purge id2entry ...");
self.conn self.conn
.execute("DELETE FROM id2entry", []) .execute("DELETE FROM id2entry", [])
.map(|_| ()) .map(|_| ())
@ -1175,7 +1156,6 @@ impl IdlSqliteWriteTransaction {
// If the table is empty, populate the versions as 0. // If the table is empty, populate the versions as 0.
let mut dbv_id2entry = self.get_db_version_key(DBV_ID2ENTRY); let mut dbv_id2entry = self.get_db_version_key(DBV_ID2ENTRY);
trace!(initial = %dbv_id2entry, "dbv_id2entry");
// Check db_version here. // Check db_version here.
// * if 0 -> create v1. // * if 0 -> create v1.
@ -1374,13 +1354,12 @@ impl IdlSqlite {
} }
pub(crate) fn get_allids_count(&self) -> Result<u64, OperationError> { pub(crate) fn get_allids_count(&self) -> Result<u64, OperationError> {
trace!("Counting allids...");
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
self.pool self.pool
.try_get() .try_get()
.expect("Unable to get connection from pool!!!") .expect("Unable to get connection from pool!!!")
.query_row("select count(id) from id2entry", [], |row| row.get(0)) .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 { pub fn read(&self) -> IdlSqliteReadTransaction {

View file

@ -1,9 +1,11 @@
use crate::value::IndexType;
use smartstring::alias::String as AttrString;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use smartstring::alias::String as AttrString;
use crate::value::IndexType;
pub type IdxSlope = u8; pub type IdxSlope = u8;
// Huge props to https://github.com/sunshowers/borrow-complex-key-example/blob/master/src/lib.rs // Huge props to https://github.com/sunshowers/borrow-complex-key-example/blob/master/src/lib.rs

View file

@ -4,35 +4,32 @@
//! is to persist content safely to disk, load that content, and execute queries //! is to persist content safely to disk, load that content, and execute queries
//! utilising indexes in the most effective way possible. //! 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::cell::UnsafeCell;
use std::fs;
use std::ops::DerefMut;
use std::sync::Arc; 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 tracing::{trace, trace_span};
use uuid::Uuid;
use crate::be::dbentry::{DbBackup, DbEntry}; use crate::be::dbentry::{DbBackup, DbEntry};
use crate::entry::{Entry, EntryCommitted, EntryNew, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryNew, EntrySealed};
use crate::filter::{Filter, FilterPlan, FilterResolved, FilterValidResolved}; use crate::filter::{Filter, FilterPlan, FilterResolved, FilterValidResolved};
use crate::identity::Limits; use crate::identity::Limits;
use crate::value::Value; use crate::prelude::*;
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::repl::cid::Cid; use crate::repl::cid::Cid;
use crate::repl::ruv::{ use crate::repl::ruv::{
ReplicationUpdateVector, ReplicationUpdateVectorReadTransaction, ReplicationUpdateVector, ReplicationUpdateVectorReadTransaction,
ReplicationUpdateVectorTransaction, ReplicationUpdateVectorWriteTransaction, ReplicationUpdateVectorTransaction, ReplicationUpdateVectorWriteTransaction,
}; };
use crate::value::{IndexType, Value};
pub mod dbentry; pub mod dbentry;
pub mod dbvalue; pub mod dbvalue;
@ -41,12 +38,10 @@ mod idl_sqlite;
pub(crate) mod idxkey; pub(crate) mod idxkey;
pub(crate) use self::idxkey::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxSlope}; pub(crate) use self::idxkey::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxSlope};
use crate::be::idl_arc_sqlite::{ use crate::be::idl_arc_sqlite::{
IdlArcSqlite, IdlArcSqliteReadTransaction, IdlArcSqliteTransaction, IdlArcSqlite, IdlArcSqliteReadTransaction, IdlArcSqliteTransaction,
IdlArcSqliteWriteTransaction, IdlArcSqliteWriteTransaction,
}; };
// Re-export this // Re-export this
pub use crate::be::idl_sqlite::FsType; 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 /// 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. /// execution log, so that it can be examined how an operation proceeded.
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
#[instrument(level = "debug", name = "be::filter2idl", skip_all)]
fn filter2idl( fn filter2idl(
&self, &self,
filt: &FilterResolved, filt: &FilterResolved,
@ -534,6 +530,7 @@ pub trait BackendTransaction {
}) })
} }
#[instrument(level = "debug", name = "be::search", skip_all)]
fn search( fn search(
&self, &self,
erl: &Limits, erl: &Limits,
@ -543,16 +540,12 @@ pub trait BackendTransaction {
// Unlike DS, even if we don't get the index back, we can just pass // Unlike DS, even if we don't get the index back, we can just pass
// to the in-memory filter test and be done. // to the in-memory filter test and be done.
spanned!("be::search", { debug!(filter_optimised = ?filt);
filter_trace!(?filt, "filter optimized");
let (idl, fplan) = trace_span!("be::search -> filter2idl").in_scope(|| { let (idl, fplan) = trace_span!("be::search -> filter2idl")
spanned!("be::search -> filter2idl", { .in_scope(|| self.filter2idl(filt.to_inner(), FILTER_SEARCH_TEST_THRESHOLD))?;
self.filter2idl(filt.to_inner(), FILTER_SEARCH_TEST_THRESHOLD)
})
})?;
filter_trace!(?fplan, "filter executed plan"); debug!(filter_executed_plan = ?fplan);
match &idl { match &idl {
IdList::AllIds => { IdList::AllIds => {
@ -593,29 +586,23 @@ pub trait BackendTransaction {
let entries_filtered = match idl { let entries_filtered = match idl {
IdList::AllIds => trace_span!("be::search<entry::ftest::allids>").in_scope(|| { IdList::AllIds => trace_span!("be::search<entry::ftest::allids>").in_scope(|| {
spanned!("be::search<entry::ftest::allids>", {
entries entries
.into_iter() .into_iter()
.filter(|e| e.entry_match_no_index(filt)) .filter(|e| e.entry_match_no_index(filt))
.collect() .collect()
})
}), }),
IdList::Partial(_) => { IdList::Partial(_) => trace_span!("be::search<entry::ftest::partial>").in_scope(|| {
trace_span!("be::search<entry::ftest::partial>").in_scope(|| {
entries entries
.into_iter() .into_iter()
.filter(|e| e.entry_match_no_index(filt)) .filter(|e| e.entry_match_no_index(filt))
.collect() .collect()
}) }),
}
IdList::PartialThreshold(_) => trace_span!("be::search<entry::ftest::thresh>") IdList::PartialThreshold(_) => trace_span!("be::search<entry::ftest::thresh>")
.in_scope(|| { .in_scope(|| {
spanned!("be::search<entry::ftest::thresh>", {
entries entries
.into_iter() .into_iter()
.filter(|e| e.entry_match_no_index(filt)) .filter(|e| e.entry_match_no_index(filt))
.collect() .collect()
})
}), }),
// Since the index fully resolved, we can shortcut the filter test step here! // Since the index fully resolved, we can shortcut the filter test step here!
IdList::Indexed(_) => { IdList::Indexed(_) => {
@ -632,37 +619,33 @@ pub trait BackendTransaction {
} }
Ok(entries_filtered) Ok(entries_filtered)
})
} }
/// Given a filter, assert some condition exists. /// Given a filter, assert some condition exists.
/// Basically, this is a specialised case of search, where we don't need to /// 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 /// load any candidates if they match. This is heavily used in uuid
/// refint and attr uniqueness. /// refint and attr uniqueness.
#[instrument(level = "debug", name = "be::exists", skip_all)]
fn exists( fn exists(
&self, &self,
erl: &Limits, erl: &Limits,
filt: &Filter<FilterValidResolved>, filt: &Filter<FilterValidResolved>,
) -> Result<bool, OperationError> { ) -> Result<bool, OperationError> {
let _entered = trace_span!("be::exists").entered(); debug!(filter_optimised = ?filt);
spanned!("be::exists", {
filter_trace!(?filt, "filter optimised");
// Using the indexes, resolve the IdList here, or AllIds. // Using the indexes, resolve the IdList here, or AllIds.
// Also get if the filter was 100% resolved or not. // Also get if the filter was 100% resolved or not.
let (idl, fplan) = spanned!("be::exists -> filter2idl", { let (idl, fplan) = self.filter2idl(filt.to_inner(), FILTER_EXISTS_TEST_THRESHOLD)?;
spanned!("be::exists -> filter2idl", {
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. // Apply limits to the IdList.
match &idl { match &idl {
IdList::AllIds => { IdList::AllIds => {
if !erl.unindexed_allow { 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); return Err(OperationError::ResourceLimit);
} }
} }
@ -691,7 +674,7 @@ pub trait BackendTransaction {
// if not 100% resolved query, apply the filter test. // if not 100% resolved query, apply the filter test.
let entries_filtered: Vec<_> = let entries_filtered: Vec<_> =
spanned!("be::exists -> entry_match_no_index", { trace_span!("be::exists<entry::ftest>").in_scope(|| {
entries entries
.into_iter() .into_iter()
.filter(|e| e.entry_match_no_index(filt)) .filter(|e| e.entry_match_no_index(filt))
@ -701,7 +684,6 @@ pub trait BackendTransaction {
Ok(!entries_filtered.is_empty()) Ok(!entries_filtered.is_empty())
} }
} // end match idl } // end match idl
}) // end spanned
} }
fn verify(&self) -> Vec<Result<(), ConsistencyError>> { fn verify(&self) -> Vec<Result<(), ConsistencyError>> {
@ -878,6 +860,7 @@ pub trait BackendTransaction {
impl<'a> BackendTransaction for BackendReadTransaction<'a> { impl<'a> BackendTransaction for BackendReadTransaction<'a> {
type IdlLayerType = IdlArcSqliteReadTransaction<'a>; type IdlLayerType = IdlArcSqliteReadTransaction<'a>;
type RuvType = ReplicationUpdateVectorReadTransaction<'a>;
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
fn get_idlayer(&self) -> &mut IdlArcSqliteReadTransaction<'a> { fn get_idlayer(&self) -> &mut IdlArcSqliteReadTransaction<'a> {
@ -895,8 +878,6 @@ impl<'a> BackendTransaction for BackendReadTransaction<'a> {
unsafe { &mut (*self.idlayer.get()) } unsafe { &mut (*self.idlayer.get()) }
} }
type RuvType = ReplicationUpdateVectorReadTransaction<'a>;
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
fn get_ruv(&self) -> &mut ReplicationUpdateVectorReadTransaction<'a> { fn get_ruv(&self) -> &mut ReplicationUpdateVectorReadTransaction<'a> {
unsafe { &mut (*self.ruv.get()) } unsafe { &mut (*self.ruv.get()) }
@ -930,14 +911,13 @@ impl<'a> BackendReadTransaction<'a> {
impl<'a> BackendTransaction for BackendWriteTransaction<'a> { impl<'a> BackendTransaction for BackendWriteTransaction<'a> {
type IdlLayerType = IdlArcSqliteWriteTransaction<'a>; type IdlLayerType = IdlArcSqliteWriteTransaction<'a>;
type RuvType = ReplicationUpdateVectorWriteTransaction<'a>;
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
fn get_idlayer(&self) -> &mut IdlArcSqliteWriteTransaction<'a> { fn get_idlayer(&self) -> &mut IdlArcSqliteWriteTransaction<'a> {
unsafe { &mut (*self.idlayer.get()) } unsafe { &mut (*self.idlayer.get()) }
} }
type RuvType = ReplicationUpdateVectorWriteTransaction<'a>;
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
fn get_ruv(&self) -> &mut ReplicationUpdateVectorWriteTransaction<'a> { fn get_ruv(&self) -> &mut ReplicationUpdateVectorWriteTransaction<'a> {
unsafe { &mut (*self.ruv.get()) } unsafe { &mut (*self.ruv.get()) }
@ -949,12 +929,12 @@ impl<'a> BackendTransaction for BackendWriteTransaction<'a> {
} }
impl<'a> BackendWriteTransaction<'a> { impl<'a> BackendWriteTransaction<'a> {
#[instrument(level = "debug", name = "be::create", skip_all)]
pub fn create( pub fn create(
&self, &self,
cid: &Cid, cid: &Cid,
entries: Vec<Entry<EntrySealed, EntryNew>>, entries: Vec<Entry<EntrySealed, EntryNew>>,
) -> Result<Vec<Entry<EntrySealed, EntryCommitted>>, OperationError> { ) -> Result<Vec<Entry<EntrySealed, EntryCommitted>>, OperationError> {
spanned!("be::create", {
if entries.is_empty() { if entries.is_empty() {
admin_error!("No entries provided to BE to create, invalid server call!"); admin_error!("No entries provided to BE to create, invalid server call!");
return Err(OperationError::EmptyRequest); return Err(OperationError::EmptyRequest);
@ -1001,16 +981,15 @@ impl<'a> BackendWriteTransaction<'a> {
} }
Ok(c_entries) Ok(c_entries)
})
} }
#[instrument(level = "debug", name = "be::modify", skip_all)]
pub fn modify( pub fn modify(
&self, &self,
cid: &Cid, cid: &Cid,
pre_entries: &[Arc<EntrySealedCommitted>], pre_entries: &[Arc<EntrySealedCommitted>],
post_entries: &[EntrySealedCommitted], post_entries: &[EntrySealedCommitted],
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("be::modify", {
if post_entries.is_empty() || pre_entries.is_empty() { if post_entries.is_empty() || pre_entries.is_empty() {
admin_error!("No entries provided to BE to modify, invalid server call!"); admin_error!("No entries provided to BE to modify, invalid server call!");
return Err(OperationError::EmptyRequest); return Err(OperationError::EmptyRequest);
@ -1043,11 +1022,10 @@ impl<'a> BackendWriteTransaction<'a> {
.iter() .iter()
.zip(post_entries.iter()) .zip(post_entries.iter())
.try_for_each(|(pre, post)| self.entry_index(Some(pre.as_ref()), Some(post))) .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> { 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 // 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. // of all the entries we need to examine.
let idl = self.get_ruv().trim_up_to(cid).map_err(|e| { 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))?; .try_for_each(|e| self.entry_index(Some(e), None))?;
Ok(sz) Ok(sz)
})
} }
#[instrument(level = "debug", name = "be::update_idxmeta", skip_all)]
pub fn update_idxmeta(&mut self, idxkeys: Vec<IdxKey>) -> Result<(), OperationError> { pub fn update_idxmeta(&mut self, idxkeys: Vec<IdxKey>) -> Result<(), OperationError> {
if self.is_idx_slopeyness_generated()? { if self.is_idx_slopeyness_generated()? {
trace!("Indexing slopes available"); 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> { pub fn ruv_rebuild(&mut self) -> Result<(), OperationError> {
// Rebuild the ruv! // Rebuild the ruv!
spanned!("server::ruv_rebuild", {
// For now this has to read from all the entries in the DB, but in the future // 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'll actually store this properly (?). If it turns out this is really fast
// we may just rebuild this always on startup. // we may just rebuild this always on startup.
@ -1540,7 +1518,6 @@ impl<'a> BackendWriteTransaction<'a> {
self.get_ruv().rebuild(&entries)?; self.get_ruv().rebuild(&entries)?;
Ok(()) Ok(())
})
} }
pub fn commit(self) -> Result<(), OperationError> { 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. // In the future this will do the routing between the chosen backends etc.
impl Backend { impl Backend {
#[instrument(level = "debug", name = "be::new", skip_all)]
pub fn new( pub fn new(
mut cfg: BackendConfig, mut cfg: BackendConfig,
// path: &str, // path: &str,
@ -1675,7 +1653,6 @@ impl Backend {
let ruv = Arc::new(ReplicationUpdateVector::default()); let ruv = Arc::new(ReplicationUpdateVector::default());
// this has a ::memory() type, but will path == "" work? // this has a ::memory() type, but will path == "" work?
spanned!("be::new", {
let idlayer = Arc::new(IdlArcSqlite::new(&cfg, vacuum)?); let idlayer = Arc::new(IdlArcSqlite::new(&cfg, vacuum)?);
let be = Backend { let be = Backend {
cfg, cfg,
@ -1708,7 +1685,6 @@ impl Backend {
})?; })?;
Ok(be) Ok(be)
})
} }
pub fn get_pool_size(&self) -> u32 { pub fn get_pool_size(&self) -> u32 {
@ -1762,22 +1738,23 @@ impl Backend {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use idlset::v2::IDLBitRange;
use std::fs; use std::fs;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use idlset::v2::IDLBitRange;
use uuid::Uuid; use uuid::Uuid;
use super::super::entry::{Entry, EntryInit, EntryNew}; use super::super::entry::{Entry, EntryInit, EntryNew};
use super::{ 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::identity::Limits;
use crate::prelude::*; use crate::prelude::*;
use crate::repl::cid::Cid; use crate::repl::cid::Cid;
use crate::value::{IndexType, PartialValue, Value}; use crate::value::{IndexType, PartialValue, Value};
use std::time::Duration;
lazy_static! { lazy_static! {
static ref CID_ZERO: Cid = unsafe { Cid::new_zero() }; static ref CID_ZERO: Cid = unsafe { Cid::new_zero() };

View file

@ -4,11 +4,12 @@
//! These components should be "per server". Any "per domain" config should be in the system //! These components should be "per server". Any "per domain" config should be in the system
//! or domain entries that are able to be replicated. //! or domain entries that are able to be replicated.
use std::fmt;
use std::str::FromStr;
use kanidm_proto::messages::ConsoleOutputMode; use kanidm_proto::messages::ConsoleOutputMode;
use rand::prelude::*; use rand::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct IntegrationTestConfig { pub struct IntegrationTestConfig {

View file

@ -1,20 +1,17 @@
use crate::be::dbvalue::DbBackupCodeV1; use std::convert::TryFrom;
use crate::be::dbvalue::{DbCred, DbPasswordV1}; use std::time::{Duration, Instant};
use hashbrown::HashMap as Map;
use hashbrown::HashSet; use hashbrown::{HashMap as Map, HashSet};
use kanidm_proto::v1::{BackupCodesView, CredentialDetail, CredentialDetailType, OperationError}; use kanidm_proto::v1::{BackupCodesView, CredentialDetail, CredentialDetailType, OperationError};
use openssl::hash::MessageDigest; use openssl::hash::MessageDigest;
use openssl::pkcs5::pbkdf2_hmac; use openssl::pkcs5::pbkdf2_hmac;
use openssl::sha::Sha512; use openssl::sha::Sha512;
use rand::prelude::*; use rand::prelude::*;
use std::convert::TryFrom;
use std::time::{Duration, Instant};
use uuid::Uuid; 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::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 policy;
pub mod softlock; pub mod softlock;
@ -234,12 +231,15 @@ impl BackupCodes {
pub fn new(code_set: HashSet<String>) -> Self { pub fn new(code_set: HashSet<String>) -> Self {
BackupCodes { code_set } BackupCodes { code_set }
} }
pub fn verify(&self, code_chal: &str) -> bool { pub fn verify(&self, code_chal: &str) -> bool {
self.code_set.contains(code_chal) self.code_set.contains(code_chal)
} }
pub fn remove(&mut self, code_chal: &str) -> bool { pub fn remove(&mut self, code_chal: &str) -> bool {
self.code_set.remove(code_chal) self.code_set.remove(code_chal)
} }
pub fn to_dbbackupcodev1(&self) -> DbBackupCodeV1 { pub fn to_dbbackupcodev1(&self) -> DbBackupCodeV1 {
DbBackupCodeV1 { DbBackupCodeV1 {
code_set: self.code_set.clone(), code_set: self.code_set.clone(),
@ -892,9 +892,10 @@ impl CredentialType {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::convert::TryFrom;
use crate::credential::policy::CryptoPolicy; use crate::credential::policy::CryptoPolicy;
use crate::credential::*; use crate::credential::*;
use std::convert::TryFrom;
#[test] #[test]
fn test_credential_simple() { fn test_credential_simple() {

View file

@ -1,6 +1,7 @@
use super::Password;
use std::time::Duration; use std::time::Duration;
use super::Password;
const PBKDF2_MIN_NIST_COST: u64 = 10000; const PBKDF2_MIN_NIST_COST: u64 = 10000;
#[derive(Debug)] #[derive(Debug)]

View file

@ -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::hash::MessageDigest;
use openssl::pkey::PKey; use openssl::pkey::PKey;
use openssl::sign::Signer; use openssl::sign::Signer;
use rand::prelude::*; use rand::prelude::*;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::time::{Duration, SystemTime};
use kanidm_proto::v1::TotpAlgo as ProtoTotpAlgo; use crate::be::dbvalue::{DbTotpAlgoV1, DbTotpV1};
use kanidm_proto::v1::TotpSecret as ProtoTotp;
// This is 64 bits of entropy, as the examples in https://tools.ietf.org/html/rfc6238 show. // This is 64 bits of entropy, as the examples in https://tools.ietf.org/html/rfc6238 show.
const SECRET_SIZE_BYTES: usize = 8; const SECRET_SIZE_BYTES: usize = 8;
@ -192,9 +191,10 @@ impl Totp {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP};
use std::time::Duration; use std::time::Duration;
use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP};
#[test] #[test]
fn hotp_basic() { fn hotp_basic() {
let otp_sha1 = Totp::new(vec![0], 30, TotpAlgo::Sha1); let otp_sha1 = Totp::new(vec![0], 30, TotpAlgo::Sha1);

View file

@ -1,10 +1,11 @@
//! This module contains cryptographic setup code, a long with what policy //! This module contains cryptographic setup code, a long with what policy
//! and ciphers we accept. //! and ciphers we accept.
use crate::config::Configuration;
use openssl::error::ErrorStack; use openssl::error::ErrorStack;
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
use crate::config::Configuration;
/// From the server configuration, generate an OpenSSL acceptor that we can use /// From the server configuration, generate an OpenSSL acceptor that we can use
/// to build our sockets for https/ldaps. /// to build our sockets for https/ldaps.
pub fn setup_tls(config: &Configuration) -> Result<Option<SslAcceptorBuilder>, ErrorStack> { pub fn setup_tls(config: &Configuration) -> Result<Option<SslAcceptorBuilder>, ErrorStack> {

View file

@ -24,6 +24,26 @@
//! [`filter`]: ../filter/index.html //! [`filter`]: ../filter/index.html
//! [`schema`]: ../schema/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::credential::Credential;
use crate::filter::{Filter, FilterInvalid, FilterResolved, FilterValidResolved}; use crate::filter::{Filter, FilterInvalid, FilterResolved, FilterValidResolved};
use crate::ldap::ldap_vattr_map; use crate::ldap::ldap_vattr_map;
@ -32,33 +52,8 @@ use crate::prelude::*;
use crate::repl::cid::Cid; use crate::repl::cid::Cid;
use crate::repl::entry::EntryChangelog; use crate::repl::entry::EntryChangelog;
use crate::schema::{SchemaAttribute, SchemaClass, SchemaTransaction}; use crate::schema::{SchemaAttribute, SchemaClass, SchemaTransaction};
use crate::value::{IndexType, SyntaxType}; use crate::value::{IndexType, IntentTokenState, PartialValue, Session, SyntaxType, Value};
use crate::value::{IntentTokenState, PartialValue, Session, Value};
use crate::valueset::{self, ValueSet}; 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::convert::TryFrom;
// use std::str::FromStr; // use std::str::FromStr;
@ -222,7 +217,6 @@ pub(crate) fn compare_attrs(left: &Eattrs, right: &Eattrs) -> bool {
/// [`schema`]: ../schema/index.html /// [`schema`]: ../schema/index.html
/// [`access`]: ../access/index.html /// [`access`]: ../access/index.html
/// [`event`]: ../event/index.html /// [`event`]: ../event/index.html
///
pub struct Entry<VALID, STATE> { pub struct Entry<VALID, STATE> {
valid: VALID, valid: VALID,
state: STATE, state: STATE,
@ -323,11 +317,11 @@ impl Entry<EntryInit, EntryNew> {
/// Given a proto entry in JSON formed as a serialised string, processed that string /// Given a proto entry in JSON formed as a serialised string, processed that string
/// into an Entry. /// into an Entry.
#[instrument(level = "debug", skip_all)]
pub fn from_proto_entry_str( pub fn from_proto_entry_str(
es: &str, es: &str,
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("from_proto_entry_str", {
if cfg!(test) { if cfg!(test) {
if es.len() > 256 { if es.len() > 256 {
let (dsp_es, _) = es.split_at(255); let (dsp_es, _) = es.split_at(255);
@ -345,7 +339,6 @@ impl Entry<EntryInit, EntryNew> {
})?; })?;
// now call from_proto_entry // now call from_proto_entry
Self::from_proto_entry(&pe, qs) Self::from_proto_entry(&pe, qs)
})
} }
#[cfg(test)] #[cfg(test)]
@ -2471,13 +2464,15 @@ impl From<&SchemaClass> for Entry<EntryInit, EntryNew> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::BTreeSet as Set;
use hashbrown::HashMap;
use smartstring::alias::String as AttrString;
use crate::be::{IdxKey, IdxSlope}; use crate::be::{IdxKey, IdxSlope};
use crate::entry::{Entry, EntryInit, EntryInvalid, EntryNew}; use crate::entry::{Entry, EntryInit, EntryInvalid, EntryNew};
use crate::modify::{Modify, ModifyList}; use crate::modify::{Modify, ModifyList};
use crate::value::{IndexType, PartialValue, Value}; use crate::value::{IndexType, PartialValue, Value};
use hashbrown::HashMap;
use smartstring::alias::String as AttrString;
use std::collections::BTreeSet as Set;
#[test] #[test]
fn test_entry_basic() { fn test_entry_basic() {

View file

@ -15,6 +15,21 @@
//! with the operation, and a clear path to know how to transform events between //! with the operation, and a clear path to know how to transform events between
//! various types. //! 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::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced};
use crate::filter::{Filter, FilterInvalid, FilterValid}; use crate::filter::{Filter, FilterInvalid, FilterValid};
use crate::identity::Limits; use crate::identity::Limits;
@ -23,24 +38,6 @@ use crate::modify::{ModifyInvalid, ModifyList, ModifyValid};
use crate::prelude::*; use crate::prelude::*;
use crate::schema::SchemaTransaction; use crate::schema::SchemaTransaction;
use crate::value::PartialValue; 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)] #[derive(Debug)]
pub struct SearchResult { pub struct SearchResult {

View file

@ -8,28 +8,28 @@
//! [`Filter`]: struct.Filter.html //! [`Filter`]: struct.Filter.html
//! [`Entry`]: ../entry/struct.Entry.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::be::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxMeta, IdxSlope};
use crate::identity::IdentityId; use crate::identity::IdentityId;
use crate::ldap::ldap_attr_filter_map; use crate::ldap::ldap_attr_filter_map;
use crate::prelude::*; use crate::prelude::*;
use crate::schema::SchemaTransaction; use crate::schema::SchemaTransaction;
use crate::value::{IndexType, PartialValue}; 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; 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 // 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 // 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. // takes "clone_value(t, a, v) instead, but that may have a similar issue.
#[instrument(level = "debug", skip_all)]
pub fn from_ro( pub fn from_ro(
ev: &Identity, ev: &Identity,
f: &ProtoFilter, f: &ProtoFilter,
qs: &QueryServerReadTransaction, qs: &QueryServerReadTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("filer::from_ro", {
let depth = FILTER_DEPTH_MAX; let depth = FILTER_DEPTH_MAX;
let mut elems = ev.limits.filter_max_elements; let mut elems = ev.limits.filter_max_elements;
Ok(Filter { Ok(Filter {
@ -504,15 +504,14 @@ impl Filter<FilterInvalid> {
inner: FilterComp::from_ro(f, qs, depth, &mut elems)?, inner: FilterComp::from_ro(f, qs, depth, &mut elems)?,
}, },
}) })
})
} }
#[instrument(level = "debug", skip_all)]
pub fn from_rw( pub fn from_rw(
ev: &Identity, ev: &Identity,
f: &ProtoFilter, f: &ProtoFilter,
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("filter::from_rw", {
let depth = FILTER_DEPTH_MAX; let depth = FILTER_DEPTH_MAX;
let mut elems = ev.limits.filter_max_elements; let mut elems = ev.limits.filter_max_elements;
Ok(Filter { Ok(Filter {
@ -520,15 +519,14 @@ impl Filter<FilterInvalid> {
inner: FilterComp::from_rw(f, qs, depth, &mut elems)?, inner: FilterComp::from_rw(f, qs, depth, &mut elems)?,
}, },
}) })
})
} }
#[instrument(level = "debug", skip_all)]
pub fn from_ldap_ro( pub fn from_ldap_ro(
ev: &Identity, ev: &Identity,
f: &LdapFilter, f: &LdapFilter,
qs: &QueryServerReadTransaction, qs: &QueryServerReadTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("filter::from_ldap_ro", {
let depth = FILTER_DEPTH_MAX; let depth = FILTER_DEPTH_MAX;
let mut elems = ev.limits.filter_max_elements; let mut elems = ev.limits.filter_max_elements;
Ok(Filter { Ok(Filter {
@ -536,7 +534,6 @@ impl Filter<FilterInvalid> {
inner: FilterComp::from_ldap_ro(f, qs, depth, &mut elems)?, inner: FilterComp::from_ldap_ro(f, qs, depth, &mut elems)?,
}, },
}) })
})
} }
} }
@ -948,7 +945,6 @@ impl PartialOrd for FilterResolved {
impl Ord for FilterResolved { impl Ord for FilterResolved {
/// Ordering of filters for optimisation and subsequent dead term elimination. /// Ordering of filters for optimisation and subsequent dead term elimination.
///
fn cmp(&self, rhs: &FilterResolved) -> Ordering { fn cmp(&self, rhs: &FilterResolved) -> Ordering {
let left_slopey = self.get_slopeyness_factor(); let left_slopey = self.get_slopeyness_factor();
let right_slopey = rhs.get_slopeyness_factor(); let right_slopey = rhs.get_slopeyness_factor();
@ -1330,10 +1326,6 @@ impl FilterResolved {
#[cfg(test)] #[cfg(test)]
mod tests { 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::cmp::{Ordering, PartialOrd};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::time::Duration; use std::time::Duration;
@ -1341,6 +1333,10 @@ mod tests {
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::v1::Filter as ProtoFilter;
use ldap3_proto::simple::LdapFilter; use ldap3_proto::simple::LdapFilter;
use crate::event::{CreateEvent, DeleteEvent};
use crate::filter::{Filter, FilterInvalid, FILTER_DEPTH_MAX};
use crate::prelude::*;
#[test] #[test]
fn test_filter_simple() { fn test_filter_simple() {
// Test construction. // Test construction.

View file

@ -3,12 +3,14 @@
//! and this provides the set of `Limits` to confine how many resources that the //! and this provides the set of `Limits` to confine how many resources that the
//! identity may consume during operations to prevent denial-of-service. //! identity may consume during operations to prevent denial-of-service.
use crate::prelude::*;
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::hash::Hash; use std::hash::Hash;
use std::sync::Arc; use std::sync::Arc;
use serde::{Deserialize, Serialize};
use crate::prelude::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/// Limits on the resources a single event can consume. These are defined per-event /// 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 /// as they are derived from the userAuthToken based on that individual session

View file

@ -1,30 +1,27 @@
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed}; use std::collections::{BTreeMap, BTreeSet};
use crate::prelude::*; use std::time::Duration;
use crate::schema::SchemaTransaction;
use kanidm_proto::v1::OperationError; use kanidm_proto::v1::{
use kanidm_proto::v1::UiHint; AuthType, BackupCodesView, CredentialStatus, OperationError, UiHint, UserAuthToken,
use kanidm_proto::v1::{AuthType, UserAuthToken}; };
use kanidm_proto::v1::{BackupCodesView, CredentialStatus}; use time::OffsetDateTime;
use uuid::Uuid;
use webauthn_rs::prelude::CredentialID; use webauthn_rs::prelude::{
use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; AuthenticationResult, CredentialID, DeviceKey as DeviceKeyV4, Passkey as PasskeyV4,
use webauthn_rs::prelude::Passkey as PasskeyV4; };
use crate::constants::UUID_ANONYMOUS; use crate::constants::UUID_ANONYMOUS;
use crate::credential::policy::CryptoPolicy; 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::group::Group;
use crate::idm::server::IdmServerProxyWriteTransaction; use crate::idm::server::IdmServerProxyWriteTransaction;
use crate::modify::{ModifyInvalid, ModifyList}; use crate::modify::{ModifyInvalid, ModifyList};
use crate::prelude::*;
use crate::schema::SchemaTransaction;
use crate::value::{IntentTokenState, PartialValue, Value}; 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! { lazy_static! {
static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account"); static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account");
static ref PVCLASS_POSIXACCOUNT: PartialValue = PartialValue::new_class("posixaccount"); static ref PVCLASS_POSIXACCOUNT: PartialValue = PartialValue::new_class("posixaccount");
@ -153,34 +150,31 @@ pub(crate) struct Account {
} }
impl Account { impl Account {
#[instrument(level = "trace", skip_all)]
pub(crate) fn try_from_entry_ro( pub(crate) fn try_from_entry_ro(
value: &Entry<EntrySealed, EntryCommitted>, value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerReadTransaction, qs: &mut QueryServerReadTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("idm::account::try_from_entry_ro", {
let groups = Group::try_from_account_entry_ro(value, qs)?; let groups = Group::try_from_account_entry_ro(value, qs)?;
try_from_entry!(value, groups) try_from_entry!(value, groups)
})
} }
#[instrument(level = "trace", skip_all)]
pub(crate) fn try_from_entry_rw( pub(crate) fn try_from_entry_rw(
value: &Entry<EntrySealed, EntryCommitted>, value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerWriteTransaction, qs: &mut QueryServerWriteTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("idm::account::try_from_entry_rw", {
let groups = Group::try_from_account_entry_rw(value, qs)?; let groups = Group::try_from_account_entry_rw(value, qs)?;
try_from_entry!(value, groups) try_from_entry!(value, groups)
})
} }
#[instrument(level = "trace", skip_all)]
pub(crate) fn try_from_entry_reduced( pub(crate) fn try_from_entry_reduced(
value: &Entry<EntryReduced, EntryCommitted>, value: &Entry<EntryReduced, EntryCommitted>,
qs: &mut QueryServerReadTransaction, qs: &mut QueryServerReadTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("idm::account::try_from_entry_reduced", {
let groups = Group::try_from_account_entry_red_ro(value, qs)?; let groups = Group::try_from_account_entry_red_ro(value, qs)?;
try_from_entry!(value, groups) try_from_entry!(value, groups)
})
} }
pub(crate) fn try_from_entry_no_groups( pub(crate) fn try_from_entry_no_groups(

View file

@ -2,34 +2,32 @@
//! Generally this has to process an authentication attempt, and validate each //! Generally this has to process an authentication attempt, and validate each
//! factor to assert that the user is legitimate. This also contains some //! factor to assert that the user is legitimate. This also contains some
//! support code for asynchronous task execution. //! 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; use std::collections::BTreeMap;
pub use std::collections::BTreeSet as Set; pub use std::collections::BTreeSet as Set;
use std::convert::TryFrom; 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::{ use webauthn_rs::prelude::{
PasskeyAuthentication, RequestChallengeResponse, SecurityKeyAuthentication, Webauthn, 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 // Each CredHandler takes one or more credentials and determines if the
// handlers requirements can be 100% fufilled. This is where MFA or other // handlers requirements can be 100% fufilled. This is where MFA or other
@ -405,7 +403,9 @@ impl CredHandler {
CredState::Denied(BAD_AUTH_TYPE_MSG) CredState::Denied(BAD_AUTH_TYPE_MSG)
} }
} }
} // end CredHandler::PasswordMfa }
// end CredHandler::PasswordMfa
/// Validate a webauthn authentication attempt /// Validate a webauthn authentication attempt
pub fn validate_webauthn( pub fn validate_webauthn(
@ -832,6 +832,16 @@ impl AuthSession {
#[cfg(test)] #[cfg(test)]
mod tests { 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::policy::CryptoPolicy;
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP}; use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
use crate::credential::{BackupCodes, Credential}; use crate::credential::{BackupCodes, Credential};
@ -842,17 +852,7 @@ mod tests {
use crate::idm::delayed::DelayedAction; use crate::idm::delayed::DelayedAction;
use crate::idm::AuthState; use crate::idm::AuthState;
use crate::prelude::*; 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 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> { fn create_pw_badlist_cache() -> HashSet<String> {
let mut s = HashSet::new(); let mut s = HashSet::new();

View file

@ -1,36 +1,28 @@
use crate::access::AccessControlsTransaction; use core::ops::Deref;
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 std::collections::BTreeMap; 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::{ use kanidm_proto::v1::{
CURegState, CUStatus, CredentialDetail, PasskeyDetail, PasswordFeedback, TotpSecret, CURegState, CUStatus, CredentialDetail, PasskeyDetail, PasswordFeedback, TotpSecret,
}; };
use serde::{Deserialize, Serialize};
use crate::utils::{backup_code_from_random, readable_password_from_random, uuid_from_duration}; use time::OffsetDateTime;
use webauthn_rs::prelude::DeviceKey as DeviceKeyV4;
use webauthn_rs::prelude::Passkey as PasskeyV4;
use webauthn_rs::prelude::{ use webauthn_rs::prelude::{
CreationChallengeResponse, PasskeyRegistration, RegisterPublicKeyCredential, CreationChallengeResponse, DeviceKey as DeviceKeyV4, Passkey as PasskeyV4, PasskeyRegistration,
RegisterPublicKeyCredential,
}; };
use serde::{Deserialize, Serialize}; use crate::access::AccessControlsTransaction;
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
use std::fmt; use crate::credential::{BackupCodes, Credential};
use std::sync::Arc; use crate::idm::account::Account;
use std::sync::Mutex; use crate::idm::server::{IdmServerCredUpdateTransaction, IdmServerProxyWriteTransaction};
use std::time::Duration; use crate::prelude::*;
use time::OffsetDateTime; use crate::utils::{backup_code_from_random, readable_password_from_random, uuid_from_duration};
use crate::value::IntentTokenState;
use core::ops::Deref;
const MAXIMUM_CRED_UPDATE_TTL: Duration = Duration::from_secs(900); const MAXIMUM_CRED_UPDATE_TTL: Duration = Duration::from_secs(900);
const MAXIMUM_INTENT_TTL: Duration = Duration::from_secs(86400); const MAXIMUM_INTENT_TTL: Duration = Duration::from_secs(86400);
@ -155,7 +147,6 @@ pub struct CredentialUpdateSessionStatus {
// The target user's display name // The target user's display name
displayname: String, displayname: String,
// ttl: Duration, // ttl: Duration,
//
can_commit: bool, can_commit: bool,
primary: Option<CredentialDetail>, primary: Option<CredentialDetail>,
passkeys: Vec<PasskeyDetail>, passkeys: Vec<PasskeyDetail>,
@ -384,12 +375,12 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
Ok((CredentialUpdateSessionToken { token_enc }, status)) Ok((CredentialUpdateSessionToken { token_enc }, status))
} }
#[instrument(level = "debug", skip_all)]
pub fn init_credential_update_intent( pub fn init_credential_update_intent(
&mut self, &mut self,
event: &InitCredentialUpdateIntentEvent, event: &InitCredentialUpdateIntentEvent,
ct: Duration, ct: Duration,
) -> Result<CredentialUpdateIntentToken, OperationError> { ) -> Result<CredentialUpdateIntentToken, OperationError> {
spanned!("idm::server::credupdatesession<Init>", {
let account = self.validate_init_credential_update(event.target, &event.ident)?; let account = self.validate_init_credential_update(event.target, &event.ident)?;
// ==== AUTHORISATION CHECKED === // ==== AUTHORISATION CHECKED ===
@ -429,8 +420,10 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
); );
// Remove any old credential update intents // Remove any old credential update intents
account.credential_update_intent_tokens.iter().for_each( account
|(existing_intent_id, state)| { .credential_update_intent_tokens
.iter()
.for_each(|(existing_intent_id, state)| {
let max_ttl = match state { let max_ttl = match state {
IntentTokenState::Valid { max_ttl } IntentTokenState::Valid { max_ttl }
| IntentTokenState::InProgress { | IntentTokenState::InProgress {
@ -447,8 +440,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
PartialValue::IntentToken(existing_intent_id.clone()), PartialValue::IntentToken(existing_intent_id.clone()),
)); ));
} }
}, });
);
self.qs_write self.qs_write
.internal_modify( .internal_modify(
@ -462,7 +454,6 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
})?; })?;
Ok(CredentialUpdateIntentToken { intent_id }) Ok(CredentialUpdateIntentToken { intent_id })
})
} }
pub fn exchange_intent_credential_update( 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) self.create_credupdate_session(session_id, Some(intent_id), account, current_time)
} }
#[instrument(level = "debug", skip_all)]
pub fn init_credential_update( pub fn init_credential_update(
&mut self, &mut self,
event: &InitCredentialUpdateEvent, event: &InitCredentialUpdateEvent,
ct: Duration, ct: Duration,
) -> Result<(CredentialUpdateSessionToken, CredentialUpdateSessionStatus), OperationError> { ) -> Result<(CredentialUpdateSessionToken, CredentialUpdateSessionStatus), OperationError> {
spanned!("idm::server::credupdatesession<Init>", {
let account = self.validate_init_credential_update(event.target, &event.ident)?; let account = self.validate_init_credential_update(event.target, &event.ident)?;
// ==== AUTHORISATION CHECKED === // ==== AUTHORISATION CHECKED ===
// This is the expiry time, so that our cleanup task can "purge up to now" rather // 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. // Build the cred update session.
self.create_credupdate_session(sessionid, None, account, ct) self.create_credupdate_session(sessionid, None, account, ct)
})
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
@ -1472,6 +1462,14 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { 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::{ use super::{
CredentialUpdateSessionStatus, CredentialUpdateSessionToken, InitCredentialUpdateEvent, CredentialUpdateSessionStatus, CredentialUpdateSessionToken, InitCredentialUpdateEvent,
InitCredentialUpdateIntentEvent, MfaRegStateStatus, MAXIMUM_CRED_UPDATE_TTL, InitCredentialUpdateIntentEvent, MfaRegStateStatus, MAXIMUM_CRED_UPDATE_TTL,
@ -1481,16 +1479,8 @@ mod tests {
use crate::event::{AuthEvent, AuthResult, CreateEvent}; use crate::event::{AuthEvent, AuthResult, CreateEvent};
use crate::idm::delayed::DelayedAction; use crate::idm::delayed::DelayedAction;
use crate::idm::server::IdmServer; use crate::idm::server::IdmServer;
use crate::prelude::*;
use std::time::Duration;
use webauthn_authenticator_rs::{softpasskey::SoftPasskey, WebauthnAuthenticator};
use crate::idm::AuthState; use crate::idm::AuthState;
use kanidm_proto::v1::{AuthAllowed, AuthMech, CredentialDetailType}; use crate::prelude::*;
use uuid::uuid;
use async_std::task;
const TEST_CURRENT_TIME: u64 = 6000; const TEST_CURRENT_TIME: u64 = 6000;
const TESTPERSON_UUID: Uuid = uuid!("cf231fea-1a8f-4410-a520-fd9b1a379c86"); const TESTPERSON_UUID: Uuid = uuid!("cf231fea-1a8f-4410-a520-fd9b1a379c86");

View file

@ -1,6 +1,7 @@
use crate::prelude::*;
use kanidm_proto::v1::OperationError; use kanidm_proto::v1::OperationError;
use crate::prelude::*;
#[cfg(test)] #[cfg(test)]
pub(crate) struct PasswordChangeEvent { pub(crate) struct PasswordChangeEvent {
pub ident: Identity, pub ident: Identity,

View file

@ -1,10 +1,9 @@
use kanidm_proto::v1::{Group as ProtoGroup, OperationError};
use uuid::Uuid;
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed};
use crate::prelude::*; use crate::prelude::*;
use crate::value::PartialValue; use crate::value::PartialValue;
use kanidm_proto::v1::Group as ProtoGroup;
use kanidm_proto::v1::OperationError;
use uuid::Uuid;
lazy_static! { lazy_static! {
static ref PVCLASS_GROUP: PartialValue = PartialValue::new_class("group"); static ref PVCLASS_GROUP: PartialValue = PartialValue::new_class("group");

View file

@ -15,10 +15,10 @@ pub mod server;
pub(crate) mod serviceaccount; pub(crate) mod serviceaccount;
pub(crate) mod unix; pub(crate) mod unix;
use kanidm_proto::v1::{AuthAllowed, AuthMech};
use std::fmt; use std::fmt;
use kanidm_proto::v1::{AuthAllowed, AuthMech};
pub enum AuthState { pub enum AuthState {
Choose(Vec<AuthMech>), Choose(Vec<AuthMech>),
Continue(Vec<AuthAllowed>), Continue(Vec<AuthAllowed>),

View file

@ -3,30 +3,19 @@
//! This contains the in memory and loaded set of active oauth2 resource server //! 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 //! integrations, which are then able to be used an accessed from the IDM layer
//! for operations involving oauth2 authentication processing. //! for operations involving oauth2 authentication processing.
//!
use crate::identity::IdentityId; use std::collections::{BTreeMap, BTreeSet};
use crate::idm::delayed::{DelayedAction, Oauth2ConsentGrant}; use std::convert::TryFrom;
use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerTransaction}; use std::fmt;
use crate::prelude::*; use std::sync::Arc;
use crate::value::OAUTHSCOPE_RE; use std::time::Duration;
use base64urlsafedata::Base64UrlSafeData; use base64urlsafedata::Base64UrlSafeData;
pub use compact_jwt::{JwkKeySet, OidcToken}; pub use compact_jwt::{JwkKeySet, OidcToken};
use compact_jwt::{JwsSigner, OidcClaims, OidcSubject}; use compact_jwt::{JwsSigner, OidcClaims, OidcSubject};
use concread::cowcell::*; use concread::cowcell::*;
use fernet::Fernet; use fernet::Fernet;
use hashbrown::HashMap; 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::{ pub use kanidm_proto::oauth2::{
AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest, AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest,
AccessTokenResponse, AuthorisationRequest, CodeChallengeMethod, ErrorResponse, AccessTokenResponse, AuthorisationRequest, CodeChallengeMethod, ErrorResponse,
@ -36,9 +25,19 @@ use kanidm_proto::oauth2::{
ClaimType, DisplayValue, GrantType, IdTokenSignAlg, ResponseMode, ResponseType, SubjectType, ClaimType, DisplayValue, GrantType, IdTokenSignAlg, ResponseMode, ResponseType, SubjectType,
TokenEndpointAuthMethod, 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 crate::identity::IdentityId;
use std::time::Duration; use crate::idm::delayed::{DelayedAction, Oauth2ConsentGrant};
use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerTransaction};
use crate::prelude::*;
use crate::value::OAUTHSCOPE_RE;
lazy_static! { lazy_static! {
static ref CLASS_OAUTH2: PartialValue = PartialValue::new_class("oauth2_resource_server"); 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)] #[cfg(test)]
mod tests { 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::delayed::DelayedAction;
use crate::idm::oauth2::{AuthoriseResponse, Oauth2Error}; use crate::idm::oauth2::{AuthoriseResponse, Oauth2Error};
use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::idm::server::{IdmServer, IdmServerTransaction};
use crate::prelude::*; 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 TEST_CURRENT_TIME: u64 = 6000;
const UAT_EXPIRE: u64 = 5; const UAT_EXPIRE: u64 = 5;
const TOKEN_EXPIRE: u64 = 900; const TOKEN_EXPIRE: u64 = 900;

View file

@ -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 uuid::Uuid;
use crate::prelude::*;
use crate::entry::{Entry, EntryCommitted, EntryReduced}; use crate::entry::{Entry, EntryCommitted, EntryReduced};
use crate::idm::group::Group;
use crate::prelude::*;
use crate::value::PartialValue; use crate::value::PartialValue;
use kanidm_proto::v1::OperationError;
use kanidm_proto::v1::RadiusAuthToken;
use std::time::Duration;
use time::OffsetDateTime;
lazy_static! { lazy_static! {
static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account"); static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account");

View file

@ -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::policy::CryptoPolicy;
use crate::credential::softlock::CredSoftLock; use crate::credential::softlock::CredSoftLock;
use crate::event::{AuthEvent, AuthEventStep, AuthResult}; use crate::event::{AuthEvent, AuthEventStep, AuthResult};
@ -5,6 +37,10 @@ use crate::identity::{IdentType, IdentUser, Limits};
use crate::idm::account::Account; use crate::idm::account::Account;
use crate::idm::authsession::AuthSession; use crate::idm::authsession::AuthSession;
use crate::idm::credupdatesession::CredentialUpdateSessionMutex; use crate::idm::credupdatesession::CredentialUpdateSessionMutex;
use crate::idm::delayed::{
DelayedAction, Oauth2ConsentGrant, PasswordUpgrade, UnixPasswordUpgrade,
WebauthnCounterIncrement,
};
#[cfg(test)] #[cfg(test)]
use crate::idm::event::PasswordChangeEvent; use crate::idm::event::PasswordChangeEvent;
use crate::idm::event::{ use crate::idm::event::{
@ -26,54 +62,6 @@ use crate::ldap::{LdapBoundToken, LdapSession};
use crate::prelude::*; use crate::prelude::*;
use crate::utils::{password_from_random, readable_password_from_random, uuid_from_duration, Sid}; 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 AuthSessionMutex = Arc<Mutex<AuthSession>>;
type CredSoftLockMutex = Arc<Mutex<CredSoftLock>>; type CredSoftLockMutex = Arc<Mutex<CredSoftLock>>;
@ -298,6 +286,7 @@ impl IdmServer {
} }
/// Read from the database, in a transaction. /// Read from the database, in a transaction.
#[instrument(level = "debug", skip_all)]
pub async fn proxy_read_async(&self) -> IdmServerProxyReadTransaction<'_> { pub async fn proxy_read_async(&self) -> IdmServerProxyReadTransaction<'_> {
IdmServerProxyReadTransaction { IdmServerProxyReadTransaction {
qs_read: self.qs.read_async().await, qs_read: self.qs.read_async().await,
@ -312,6 +301,7 @@ impl IdmServer {
task::block_on(self.proxy_write_async(ts)) task::block_on(self.proxy_write_async(ts))
} }
#[instrument(level = "debug", skip_all)]
pub async fn proxy_write_async(&self, ts: Duration) -> IdmServerProxyWriteTransaction<'_> { pub async fn proxy_write_async(&self, ts: Duration) -> IdmServerProxyWriteTransaction<'_> {
let mut sid = [0; 4]; let mut sid = [0; 4];
let mut rng = StdRng::from_entropy(); 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 /// 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 /// that we internally sign with. We can use this to select the appropriate token type
/// and validation method. /// and validation method.
#[instrument(level = "info", skip_all)]
fn validate_and_parse_token_to_ident( fn validate_and_parse_token_to_ident(
&self, &self,
token: Option<&str>, token: Option<&str>,
@ -532,6 +523,7 @@ pub(crate) trait IdmServerTransaction<'a> {
} }
} }
#[instrument(level = "debug", skip_all)]
fn validate_and_parse_uat( fn validate_and_parse_uat(
&self, &self,
token: Option<&str>, token: Option<&str>,
@ -598,6 +590,7 @@ pub(crate) trait IdmServerTransaction<'a> {
/// something we can pin access controls and other limits and references to. /// 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 /// This is why it is the location where validity windows are checked and other
/// relevant session information is injected. /// relevant session information is injected.
#[instrument(level = "debug", skip_all)]
fn process_uat_to_identity( fn process_uat_to_identity(
&self, &self,
uat: &UserAuthToken, uat: &UserAuthToken,
@ -663,6 +656,7 @@ pub(crate) trait IdmServerTransaction<'a> {
}) })
} }
#[instrument(level = "debug", skip_all)]
fn process_apit_to_identity( fn process_apit_to_identity(
&self, &self,
apit: &ApiToken, apit: &ApiToken,
@ -683,6 +677,7 @@ pub(crate) trait IdmServerTransaction<'a> {
}) })
} }
#[instrument(level = "debug", skip_all)]
fn validate_ldap_session( fn validate_ldap_session(
&self, &self,
session: &LdapSession, session: &LdapSession,
@ -883,7 +878,6 @@ impl<'a> IdmServerAuthTransaction<'a> {
match auth_session { match auth_session {
Some(auth_session) => { Some(auth_session) => {
let mut session_write = self.sessions.write(); let mut session_write = self.sessions.write();
spanned!("idm::server::auth<Init> -> sessions", {
if session_write.contains_key(&sessionid) { if session_write.contains_key(&sessionid) {
Err(OperationError::InvalidSessionState) Err(OperationError::InvalidSessionState)
} else { } else {
@ -891,8 +885,7 @@ impl<'a> IdmServerAuthTransaction<'a> {
// Debugging: ensure we really inserted ... // Debugging: ensure we really inserted ...
debug_assert!(session_write.get(&sessionid).is_some()); debug_assert!(session_write.get(&sessionid).is_some());
Ok(()) Ok(())
} }?;
})?;
session_write.commit(); session_write.commit();
} }
None => { None => {
@ -2024,8 +2017,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
} }
} }
#[instrument(level = "debug", skip_all)]
pub fn commit(mut self) -> Result<(), OperationError> { pub fn commit(mut self) -> Result<(), OperationError> {
spanned!("idm::server::IdmServerProxyWriteTransaction::commit", {
if self if self
.qs_write .qs_write
.get_changed_uuids() .get_changed_uuids()
@ -2082,7 +2075,6 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
self.cred_update_sessions.commit(); self.cred_update_sessions.commit();
trace!("cred_update_session.commit"); trace!("cred_update_session.commit");
self.qs_write.commit() self.qs_write.commit()
})
} }
fn reload_password_badlist(&mut self) -> Result<(), OperationError> { fn reload_password_badlist(&mut self) -> Result<(), OperationError> {
@ -2100,6 +2092,14 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { 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::policy::CryptoPolicy;
use crate::credential::{Credential, Password}; use crate::credential::{Credential, Password};
use crate::event::{AuthEvent, AuthResult, CreateEvent, ModifyEvent}; use crate::event::{AuthEvent, AuthResult, CreateEvent, ModifyEvent};
@ -2107,20 +2107,12 @@ mod tests {
PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent, PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent,
UnixGroupTokenEvent, UnixPasswordChangeEvent, UnixUserAuthEvent, UnixUserTokenEvent, UnixGroupTokenEvent, UnixPasswordChangeEvent, UnixUserAuthEvent, UnixUserTokenEvent,
}; };
use crate::idm::server::{IdmServer, IdmServerTransaction};
use crate::idm::AuthState; use crate::idm::AuthState;
use crate::modify::{Modify, ModifyList}; use crate::modify::{Modify, ModifyList};
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::OperationError;
use kanidm_proto::v1::{AuthAllowed, AuthMech, AuthType};
use crate::idm::server::{IdmServer, IdmServerTransaction};
// , IdmServerDelayed; // , IdmServerDelayed;
use crate::utils::duration_from_epoch_now; 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: &'static str = "ntaoeuntnaoeuhraohuercahu😍";
const TEST_PASSWORD_INC: &'static str = "ntaoentu nkrcgaeunhibwmwmqj;k wqjbkx "; const TEST_PASSWORD_INC: &'static str = "ntaoentu nkrcgaeunhibwmwmqj;k wqjbkx ";

View file

@ -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::event::SearchEvent;
use crate::idm::account::Account; use crate::idm::account::Account;
use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerProxyWriteTransaction}; use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerProxyWriteTransaction};
use crate::prelude::*; use crate::prelude::*;
use crate::value::Session; 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 add KID to es256 der for lookups ✅
// Need to generate the es256 on the account on modifies ✅ // Need to generate the es256 on the account on modifies ✅
@ -87,14 +87,13 @@ pub struct ServiceAccount {
} }
impl ServiceAccount { impl ServiceAccount {
#[instrument(level = "debug", skip_all)]
pub(crate) fn try_from_entry_rw( pub(crate) fn try_from_entry_rw(
value: &Entry<EntrySealed, EntryCommitted>, value: &Entry<EntrySealed, EntryCommitted>,
// qs: &mut QueryServerWriteTransaction, // qs: &mut QueryServerWriteTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
spanned!("idm::serviceaccount::try_from_entry_rw", {
// let groups = Group::try_from_account_entry_rw(value, qs)?; // let groups = Group::try_from_account_entry_rw(value, qs)?;
try_from_entry!(value) try_from_entry!(value)
})
} }
pub(crate) fn check_api_token_valid( pub(crate) fn check_api_token_valid(
@ -354,16 +353,17 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { 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::str::FromStr;
use std::time::Duration; 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; const TEST_CURRENT_TIME: u64 = 6000;
#[test] #[test]

View file

@ -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 uuid::Uuid;
use crate::credential::policy::CryptoPolicy; 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::modify::{ModifyInvalid, ModifyList};
use crate::prelude::*; 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)] #[derive(Debug, Clone)]
pub(crate) struct UnixUserAccount { pub(crate) struct UnixUserAccount {

View file

@ -1,20 +1,20 @@
//! This contains scheduled tasks/interval tasks that are run inside of the server on a schedule //! This contains scheduled tasks/interval tasks that are run inside of the server on a schedule
//! as background operations. //! as background operations.
use crate::actors::v1_read::QueryServerReadV1; use std::fs;
use crate::actors::v1_write::QueryServerWriteV1; use std::path::Path;
use crate::config::OnlineBackup;
use crate::constants::PURGE_FREQUENCY;
use crate::event::{OnlineBackupEvent, PurgeRecycledEvent, PurgeTombstoneEvent};
use chrono::Utc; use chrono::Utc;
use saffron::parse::{CronExpr, English}; use saffron::parse::{CronExpr, English};
use saffron::Cron; use saffron::Cron;
use std::fs;
use std::path::Path;
use tokio::time::{interval, sleep, Duration}; 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; pub struct IntervalActor;
impl IntervalActor { impl IntervalActor {

View file

@ -1,18 +1,20 @@
//! LDAP specific operations handling components. This is where LDAP operations //! LDAP specific operations handling components. This is where LDAP operations
//! are sent to for processing. //! 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::event::SearchEvent;
use crate::idm::event::{LdapAuthEvent, LdapTokenAuthEvent}; use crate::idm::event::{LdapAuthEvent, LdapTokenAuthEvent};
use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::idm::server::{IdmServer, IdmServerTransaction};
use crate::prelude::*; 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, // 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. // 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( async fn do_search(
&self, &self,
idms: &IdmServer, idms: &IdmServer,
@ -252,7 +255,6 @@ impl LdapServer {
let ct = duration_from_epoch_now(); let ct = duration_from_epoch_now();
let idm_read = idms.proxy_read_async().await; let idm_read = idms.proxy_read_async().await;
spanned!("ldap::do_search<core>", {
// Now start the txn - we need it for resolving filter components. // Now start the txn - we need it for resolving filter components.
// join the filter, with ext_filter // join the filter, with ext_filter
@ -287,20 +289,14 @@ impl LdapServer {
// Build the event, with the permissions from effective_session // Build the event, with the permissions from effective_session
// //
// ! Remember, searchEvent wraps to ignore hidden for us. // ! Remember, searchEvent wraps to ignore hidden for us.
let se = spanned!("ldap::do_search<core><prepare_se>", {
let ident = idm_read let ident = idm_read
.validate_ldap_session(&uat.effective_session, ct) .validate_ldap_session(&uat.effective_session, ct)
.map_err(|e| { .map_err(|e| {
admin_error!("Invalid identity: {:?}", e); admin_error!("Invalid identity: {:?}", e);
e e
})?; })?;
SearchEvent::new_ext_impersonate_uuid( let se =
&idm_read.qs_read, SearchEvent::new_ext_impersonate_uuid(&idm_read.qs_read, ident, &lfilter, k_attrs)
ident,
&lfilter,
k_attrs,
)
})
.map_err(|e| { .map_err(|e| {
admin_error!("failed to create search event -> {:?}", e); admin_error!("failed to create search event -> {:?}", e);
e e
@ -314,7 +310,6 @@ impl LdapServer {
// These have already been fully reduced (access controls applied), // These have already been fully reduced (access controls applied),
// so we can just transform the values and open palm slam them into // so we can just transform the values and open palm slam them into
// the result structure. // the result structure.
let lres = spanned!("ldap::do_search<core><prepare results>", {
let lres: Result<Vec<_>, _> = res let lres: Result<Vec<_>, _> = res
.into_iter() .into_iter()
.map(|e| { .map(|e| {
@ -324,8 +319,6 @@ impl LdapServer {
}) })
.chain(iter::once(Ok(sr.gen_success()))) .chain(iter::once(Ok(sr.gen_success())))
.collect(); .collect();
lres
});
let lres = lres.map_err(|e| { let lres = lres.map_err(|e| {
admin_error!("entry resolve failure {:?}", e); admin_error!("entry resolve failure {:?}", e);
@ -338,7 +331,6 @@ impl LdapServer {
); );
Ok(lres) Ok(lres)
})
} }
} }
@ -550,18 +542,19 @@ pub(crate) fn ldap_attr_filter_map(input: &str) -> AttrString {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
// use crate::prelude::*; // use crate::prelude::*;
use crate::event::{CreateEvent, ModifyEvent}; use std::str::FromStr;
use crate::idm::event::UnixPasswordChangeEvent;
use crate::idm::serviceaccount::GenerateApiTokenEvent;
use crate::ldap::{LdapServer, LdapSession};
use async_std::task; use async_std::task;
use compact_jwt::{Jws, JwsUnverified};
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::ApiToken; use kanidm_proto::v1::ApiToken;
use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope}; use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope};
use ldap3_proto::simple::*; 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😍"; const TEST_PASSWORD: &'static str = "ntaoeuntnaoeuhraohuercahu😍";

View file

@ -63,39 +63,36 @@ pub mod config;
/// A prelude of imports that should be imported by all other Kanidm modules to /// A prelude of imports that should be imported by all other Kanidm modules to
/// help make imports cleaner. /// help make imports cleaner.
pub mod prelude { pub mod prelude {
pub use crate::utils::duration_from_epoch_now;
pub use kanidm_proto::v1::{ConsistencyError, OperationError}; 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 smartstring::alias::String as AttrString;
pub use url::Url; pub use url::Url;
pub use uuid::Uuid; pub use uuid::Uuid;
pub use crate::constants::*; 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::{ pub use crate::entry::{
Entry, EntryCommitted, EntryInit, EntryInvalid, EntryInvalidCommitted, EntryNew, Entry, EntryCommitted, EntryInit, EntryInvalid, EntryInvalidCommitted, EntryNew,
EntryReduced, EntrySealed, EntrySealedCommitted, EntryTuple, EntryValid, 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::identity::Identity;
pub use crate::modify::{m_pres, m_purge, m_remove, Modify, ModifyInvalid, ModifyList};
pub use crate::server::{ pub use crate::server::{
QueryServer, QueryServerReadTransaction, QueryServerTransaction, QueryServer, QueryServerReadTransaction, QueryServerTransaction,
QueryServerWriteTransaction, QueryServerWriteTransaction,
}; };
pub use crate::utils::duration_from_epoch_now;
pub use crate::value::{IndexType, PartialValue, SyntaxType, Value}; pub use crate::value::{IndexType, PartialValue, SyntaxType, Value};
pub use crate::valueset::{ pub use crate::valueset::{
ValueSet, ValueSetBool, ValueSetCid, ValueSetIndex, ValueSetIutf8, ValueSetRefer, ValueSet, ValueSetBool, ValueSetCid, ValueSetIndex, ValueSetIutf8, ValueSetRefer,
ValueSetSecret, ValueSetSpn, ValueSetSyntax, ValueSetT, ValueSetUint32, ValueSetUtf8, ValueSetSecret, ValueSetSpn, ValueSetSyntax, ValueSetT, ValueSetUint32, ValueSetUtf8,
ValueSetUuid, 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,
};
} }

View file

@ -19,9 +19,10 @@ macro_rules! setup_test {
( (
$preload_entries:expr $preload_entries:expr
) => {{ ) => {{
use crate::utils::duration_from_epoch_now;
use async_std::task; use async_std::task;
use crate::utils::duration_from_epoch_now;
let _ = sketching::test_init(); let _ = sketching::test_init();
// Create an in memory BE // Create an in memory BE
@ -105,10 +106,11 @@ macro_rules! run_test {
#[cfg(test)] #[cfg(test)]
macro_rules! entry_str_to_account { macro_rules! entry_str_to_account {
($entry_str:expr) => {{ ($entry_str:expr) => {{
use std::iter::once;
use crate::entry::{Entry, EntryInvalid, EntryNew}; use crate::entry::{Entry, EntryInvalid, EntryNew};
use crate::idm::account::Account; use crate::idm::account::Account;
use crate::value::Value; use crate::value::Value;
use std::iter::once;
let mut e: Entry<EntryInvalid, EntryNew> = let mut e: Entry<EntryInvalid, EntryNew> =
unsafe { Entry::unsafe_from_entry_str($entry_str).into_invalid_new() }; 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::schema::Schema;
use crate::utils::duration_from_epoch_now; use crate::utils::duration_from_epoch_now;
spanned!("plugins::macros::run_create_test", {
let qs = setup_test!($preload_entries); let qs = setup_test!($preload_entries);
let ce = match $internal { let ce = match $internal {
@ -225,7 +226,6 @@ macro_rules! run_create_test {
let ver = qs.verify(); let ver = qs.verify();
trace!("verification -> {:?}", ver); trace!("verification -> {:?}", ver);
assert!(ver.len() == 0); assert!(ver.len() == 0);
});
}}; }};
} }
@ -246,14 +246,11 @@ macro_rules! run_modify_test {
use crate::prelude::*; use crate::prelude::*;
use crate::schema::Schema; use crate::schema::Schema;
spanned!("plugins::macros::run_modify_test", {
let qs = setup_test!($preload_entries); let qs = setup_test!($preload_entries);
{ {
let qs_write = qs.write(duration_from_epoch_now()); 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!"); 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 qs_write = qs.write(duration_from_epoch_now());
let r = spanned!("plugins::macros::run_modify_test -> main_test", { let r = qs_write.modify(&me);
qs_write.modify(&me) $check(&qs_write);
});
spanned!("plugins::macros::run_modify_test -> post_test check", {
$check(&qs_write)
});
trace!("test result: {:?}", r); trace!("test result: {:?}", r);
assert!(r == $expect); assert!(r == $expect);
match r { match r {
@ -288,7 +281,6 @@ macro_rules! run_modify_test {
let ver = qs.verify(); let ver = qs.verify();
trace!("verification -> {:?}", ver); trace!("verification -> {:?}", ver);
assert!(ver.len() == 0); assert!(ver.len() == 0);
});
}}; }};
} }
@ -308,7 +300,6 @@ macro_rules! run_delete_test {
use crate::schema::Schema; use crate::schema::Schema;
use crate::utils::duration_from_epoch_now; use crate::utils::duration_from_epoch_now;
spanned!("plugins::macros::run_delete_test", {
let qs = setup_test!($preload_entries); let qs = setup_test!($preload_entries);
let de = match $internal { let de = match $internal {
@ -338,7 +329,6 @@ macro_rules! run_delete_test {
let ver = qs.verify(); let ver = qs.verify();
trace!("verification -> {:?}", ver); trace!("verification -> {:?}", ver);
assert!(ver.len() == 0); assert!(ver.len() == 0);
});
}}; }};
} }

View file

@ -2,19 +2,19 @@
//! express the series of Modifications that should be applied. These are expressed //! express the series of Modifications that should be applied. These are expressed
//! as "states" on what attribute-values should appear as within the `Entry` //! as "states" on what attribute-values should appear as within the `Entry`
use crate::prelude::*; use std::slice;
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 kanidm_proto::v1::{
Entry as ProtoEntry, Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError,
SchemaError,
};
// Should this be std? // Should this be std?
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smartstring::alias::String as AttrString; 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)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ModifyValid; pub struct ModifyValid;
@ -69,8 +69,8 @@ pub struct ModifyList<VALID> {
} }
impl<'a> IntoIterator for &'a ModifyList<ModifyValid> { impl<'a> IntoIterator for &'a ModifyList<ModifyValid> {
type Item = &'a Modify;
type IntoIter = slice::Iter<'a, Modify>; type IntoIter = slice::Iter<'a, Modify>;
type Item = &'a Modify;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.mods.iter() self.mods.iter()

View file

@ -4,14 +4,15 @@
// both change approaches. // both change approaches.
// //
// //
use std::collections::BTreeMap;
use kanidm_proto::v1::{ConsistencyError, PluginError};
use tracing::trace;
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;
use crate::prelude::*; use crate::prelude::*;
use crate::schema::SchemaTransaction; use crate::schema::SchemaTransaction;
use kanidm_proto::v1::{ConsistencyError, PluginError};
use tracing::trace;
use std::collections::BTreeMap;
pub struct AttrUnique; pub struct AttrUnique;
@ -192,9 +193,10 @@ impl Plugin for AttrUnique {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::prelude::*;
use kanidm_proto::v1::PluginError; use kanidm_proto::v1::PluginError;
use crate::prelude::*;
// Test entry in db, and same name, reject. // Test entry in db, and same name, reject.
#[test] #[test]
fn test_pre_create_name_unique() { fn test_pre_create_name_unique() {

View file

@ -1,12 +1,13 @@
use crate::plugins::Plugin;
use hashbrown::HashSet;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::iter::once; use std::iter::once;
use hashbrown::HashSet;
use kanidm_proto::v1::{ConsistencyError, PluginError};
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::modify::Modify; use crate::modify::Modify;
use crate::plugins::Plugin;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::{ConsistencyError, PluginError};
lazy_static! { lazy_static! {
static ref CLASS_OBJECT: Value = Value::new_class("object"); static ref CLASS_OBJECT: Value = Value::new_class("object");
@ -43,15 +44,9 @@ impl Plugin for Base {
// debug!("Entering base pre_create_transform"); // debug!("Entering base pre_create_transform");
// For each candidate // For each candidate
for entry in cand.iter_mut() { for entry in cand.iter_mut() {
trace!("Base check on entry: {:?}", entry);
// First, ensure we have the 'object', class in the class set. // First, ensure we have the 'object', class in the class set.
entry.add_ava("class", CLASS_OBJECT.clone()); 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. // if they don't have uuid, create it.
match entry.get_ava_set("uuid").map(|s| s.len()) { match entry.get_ava_set("uuid").map(|s| s.len()) {
None => { None => {
@ -85,7 +80,6 @@ impl Plugin for Base {
let uuid_ref: Uuid = entry let uuid_ref: Uuid = entry
.get_ava_single_uuid("uuid") .get_ava_single_uuid("uuid")
.ok_or_else(|| OperationError::InvalidAttribute("uuid".to_string()))?; .ok_or_else(|| OperationError::InvalidAttribute("uuid".to_string()))?;
trace!("Entry valid UUID: {:?}", entry);
if !cand_uuid.insert(uuid_ref) { if !cand_uuid.insert(uuid_ref) {
trace!("uuid duplicate found in create set! {:?}", uuid_ref); trace!("uuid duplicate found in create set! {:?}", uuid_ref);
return Err(OperationError::Plugin(PluginError::Base( return Err(OperationError::Plugin(PluginError::Base(
@ -224,9 +218,10 @@ impl Plugin for Base {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::prelude::*;
use kanidm_proto::v1::PluginError; use kanidm_proto::v1::PluginError;
use crate::prelude::*;
const JSON_ADMIN_ALLOW_ALL: &'static str = r#"{ const JSON_ADMIN_ALLOW_ALL: &'static str = r#"{
"attrs": { "attrs": {
"class": [ "class": [

View file

@ -4,15 +4,16 @@
// The primary point of this is to generate a unique domain UUID on startup // 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 // which is importart for management of the replication topo and trust
// relationships. // relationships.
use crate::plugins::Plugin; use std::iter::once;
use crate::event::{CreateEvent, ModifyEvent};
use crate::prelude::*;
use compact_jwt::JwsSigner; use compact_jwt::JwsSigner;
use kanidm_proto::v1::OperationError; use kanidm_proto::v1::OperationError;
use std::iter::once;
use tracing::trace; use tracing::trace;
use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin;
use crate::prelude::*;
lazy_static! { lazy_static! {
static ref PVCLASS_DOMAIN_INFO: PartialValue = PartialValue::new_class("domain_info"); static ref PVCLASS_DOMAIN_INFO: PartialValue = PartialValue::new_class("domain_info");
static ref PVUUID_DOMAIN_INFO: PartialValue = PartialValue::new_uuid(*UUID_DOMAIN_INFO); static ref PVUUID_DOMAIN_INFO: PartialValue = PartialValue::new_uuid(*UUID_DOMAIN_INFO);

View file

@ -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::event::{CreateEvent, ModifyEvent};
use crate::filter::FilterInvalid; use crate::filter::FilterInvalid;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::Filter as ProtoFilter;
use std::collections::BTreeMap;
use std::sync::Arc;
lazy_static! { lazy_static! {
static ref CLASS_DYNGROUP: PartialValue = PartialValue::new_class("dyngroup"); static ref CLASS_DYNGROUP: PartialValue = PartialValue::new_class("dyngroup");
@ -361,9 +363,10 @@ impl DynGroup {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::prelude::*;
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::v1::Filter as ProtoFilter;
use crate::prelude::*;
const UUID_TEST_GROUP: Uuid = uuid::uuid!("7bfd9931-06c2-4608-8a46-78719bb746fe"); const UUID_TEST_GROUP: Uuid = uuid::uuid!("7bfd9931-06c2-4608-8a46-78719bb746fe");
#[test] #[test]

View file

@ -1,11 +1,12 @@
// A plugin that generates gid numbers on types that require them for posix // A plugin that generates gid numbers on types that require them for posix
// support. // support.
use std::iter::once;
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::uuid_to_gid_u32; use crate::utils::uuid_to_gid_u32;
use std::iter::once;
/// Systemd dynamic units allocate between 6118465519, most distros allocate /// Systemd dynamic units allocate between 6118465519, most distros allocate
/// system uids from 0 - 1000, and many others give user ids between 1000 to /// system uids from 0 - 1000, and many others give user ids between 1000 to

View file

@ -1,8 +1,9 @@
use compact_jwt::JwsSigner;
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::password_from_random; use crate::utils::password_from_random;
use compact_jwt::JwsSigner;
lazy_static! { lazy_static! {
static ref CLASS_OAUTH2_BASIC: PartialValue = static ref CLASS_OAUTH2_BASIC: PartialValue =

View file

@ -10,16 +10,17 @@
// As a result, we first need to run refint to clean up all dangling references, then memberof // As a result, we first need to run refint to clean up all dangling references, then memberof
// fixes the graph of memberships // 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::entry::{Entry, EntryCommitted, EntrySealed, EntryTuple};
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;
use crate::prelude::*; use crate::prelude::*;
use crate::value::{PartialValue, Value}; use crate::value::{PartialValue, Value};
use kanidm_proto::v1::{ConsistencyError, OperationError};
use std::collections::BTreeSet;
use hashbrown::HashMap;
use std::sync::Arc;
lazy_static! { lazy_static! {
static ref CLASS_GROUP: PartialValue = PartialValue::new_class("group"); static ref CLASS_GROUP: PartialValue = PartialValue::new_class("group");

View file

@ -3,12 +3,13 @@
//! helps to ensure that data is always in specific known states within the //! helps to ensure that data is always in specific known states within the
//! `QueryServer` //! `QueryServer`
use std::sync::Arc;
use kanidm_proto::v1::{ConsistencyError, OperationError};
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::{ConsistencyError, OperationError};
use std::sync::Arc;
use tracing::trace_span;
mod attrunique; mod attrunique;
mod base; mod base;
@ -118,12 +119,12 @@ macro_rules! run_verify_plugin {
} }
impl Plugins { impl Plugins {
#[instrument(level = "debug", name = "plugins::run_pre_create_transform", skip_all)]
pub fn run_pre_create_transform( pub fn run_pre_create_transform(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
cand: &mut Vec<Entry<EntryInvalid, EntryNew>>, cand: &mut Vec<Entry<EntryInvalid, EntryNew>>,
ce: &CreateEvent, ce: &CreateEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_pre_create_transform", {
base::Base::pre_create_transform(qs, cand, ce) base::Base::pre_create_transform(qs, cand, ce)
.and_then(|_| password_import::PasswordImport::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)) .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)) .and_then(|_| spn::Spn::pre_create_transform(qs, cand, ce))
// Should always be last // Should always be last
.and_then(|_| attrunique::AttrUnique::pre_create_transform(qs, cand, ce)) .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( pub fn run_pre_create(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
cand: &[Entry<EntrySealed, EntryNew>], cand: &[Entry<EntrySealed, EntryNew>],
ce: &CreateEvent, ce: &CreateEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_pre_create", {
protected::Protected::pre_create(qs, cand, ce) protected::Protected::pre_create(qs, cand, ce)
})
} }
#[instrument(level = "debug", name = "plugins::run_post_create", skip_all)]
pub fn run_post_create( pub fn run_post_create(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
cand: &[Entry<EntrySealed, EntryCommitted>], cand: &[Entry<EntrySealed, EntryCommitted>],
ce: &CreateEvent, ce: &CreateEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_post_create", {
refint::ReferentialIntegrity::post_create(qs, cand, ce) refint::ReferentialIntegrity::post_create(qs, cand, ce)
.and_then(|_| memberof::MemberOf::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( pub fn run_pre_modify(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>, cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>,
me: &ModifyEvent, me: &ModifyEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_pre_modify", {
protected::Protected::pre_modify(qs, cand, me) protected::Protected::pre_modify(qs, cand, me)
.and_then(|_| base::Base::pre_modify(qs, cand, me)) .and_then(|_| base::Base::pre_modify(qs, cand, me))
.and_then(|_| password_import::PasswordImport::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)) .and_then(|_| spn::Spn::pre_modify(qs, cand, me))
// attr unique should always be last // attr unique should always be last
.and_then(|_| attrunique::AttrUnique::pre_modify(qs, cand, me)) .and_then(|_| attrunique::AttrUnique::pre_modify(qs, cand, me))
})
} }
#[instrument(level = "debug", name = "plugins::run_post_modify", skip_all)]
pub fn run_post_modify( pub fn run_post_modify(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
pre_cand: &[Arc<Entry<EntrySealed, EntryCommitted>>], pre_cand: &[Arc<Entry<EntrySealed, EntryCommitted>>],
cand: &[Entry<EntrySealed, EntryCommitted>], cand: &[Entry<EntrySealed, EntryCommitted>],
me: &ModifyEvent, me: &ModifyEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_post_modify", {
refint::ReferentialIntegrity::post_modify(qs, pre_cand, cand, me) refint::ReferentialIntegrity::post_modify(qs, pre_cand, cand, me)
.and_then(|_| spn::Spn::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)) .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( pub fn run_pre_delete(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>, cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>,
de: &DeleteEvent, de: &DeleteEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_pre_delete", {
protected::Protected::pre_delete(qs, cand, de) protected::Protected::pre_delete(qs, cand, de)
})
} }
#[instrument(level = "debug", name = "plugins::run_post_delete", skip_all)]
pub fn run_post_delete( pub fn run_post_delete(
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
cand: &[Entry<EntrySealed, EntryCommitted>], cand: &[Entry<EntrySealed, EntryCommitted>],
de: &DeleteEvent, de: &DeleteEvent,
) -> Result<(), OperationError> { ) -> Result<(), OperationError> {
spanned!("plugins::run_post_delete", {
refint::ReferentialIntegrity::post_delete(qs, cand, de) refint::ReferentialIntegrity::post_delete(qs, cand, de)
.and_then(|_| memberof::MemberOf::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( pub fn run_verify(
qs: &QueryServerReadTransaction, qs: &QueryServerReadTransaction,
results: &mut Vec<Result<(), ConsistencyError>>, 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, base::Base);
run_verify_plugin!(qs, results, attrunique::AttrUnique); run_verify_plugin!(qs, results, attrunique::AttrUnique);
run_verify_plugin!(qs, results, refint::ReferentialIntegrity); run_verify_plugin!(qs, results, refint::ReferentialIntegrity);
run_verify_plugin!(qs, results, dyngroup::DynGroup); run_verify_plugin!(qs, results, dyngroup::DynGroup);
run_verify_plugin!(qs, results, memberof::MemberOf); run_verify_plugin!(qs, results, memberof::MemberOf);
run_verify_plugin!(qs, results, spn::Spn); run_verify_plugin!(qs, results, spn::Spn);
})
} }
} }

View file

@ -1,11 +1,13 @@
// Transform password import requests into proper kanidm credentials. // 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::credential::{Credential, Password};
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::PluginError;
use std::convert::TryFrom;
use std::iter::once;
pub struct PasswordImport {} pub struct PasswordImport {}

View file

@ -1,12 +1,12 @@
// System protected objects. Items matching specific requirements // System protected objects. Items matching specific requirements
// may only have certain modifications performed. // may only have certain modifications performed.
use crate::plugins::Plugin; use hashbrown::HashSet;
use crate::prelude::*;
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
use crate::modify::Modify; use crate::modify::Modify;
use hashbrown::HashSet; use crate::plugins::Plugin;
use crate::prelude::*;
pub struct Protected {} pub struct Protected {}

View file

@ -9,19 +9,19 @@
// when that is written, as they *both* manipulate and alter entry reference // when that is written, as they *both* manipulate and alter entry reference
// data, so we should be careful not to step on each other. // data, so we should be careful not to step on each other.
use hashbrown::HashSet as Set;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::sync::Arc;
use crate::plugins::Plugin; use hashbrown::HashSet as Set;
use crate::prelude::*; use kanidm_proto::v1::{ConsistencyError, PluginError};
use tracing::trace;
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
use crate::filter::f_eq; use crate::filter::f_eq;
use crate::modify::Modify; use crate::modify::Modify;
use crate::plugins::Plugin;
use crate::prelude::*;
use crate::schema::SchemaTransaction; use crate::schema::SchemaTransaction;
use kanidm_proto::v1::{ConsistencyError, PluginError};
use std::sync::Arc;
use tracing::trace;
// NOTE: This *must* be after base.rs!!! // NOTE: This *must* be after base.rs!!!
@ -265,9 +265,10 @@ impl Plugin for ReferentialIntegrity {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::prelude::*;
use kanidm_proto::v1::PluginError; use kanidm_proto::v1::PluginError;
use crate::prelude::*;
// The create references a uuid that doesn't exist - reject // The create references a uuid that doesn't exist - reject
#[test] #[test]
fn test_create_uuid_reference_not_exist() { fn test_create_uuid_reference_not_exist() {

View file

@ -1,16 +1,17 @@
// Generate and manage spn's for all entries in the domain. Also deals with // Generate and manage spn's for all entries in the domain. Also deals with
// the infrequent - but possible - case where a domain is renamed. // the infrequent - but possible - case where a domain is renamed.
use crate::plugins::Plugin; use std::iter::once;
use crate::prelude::*; use std::sync::Arc;
// use crate::value::{PartialValue, Value};
use kanidm_proto::v1::{ConsistencyError, OperationError};
use crate::constants::UUID_DOMAIN_INFO; use crate::constants::UUID_DOMAIN_INFO;
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin;
use crate::prelude::*;
use crate::value::PartialValue; 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 {} pub struct Spn {}

View file

@ -1,7 +1,8 @@
use kanidm_proto::v1::OperationError;
use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::OperationError;
use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)] #[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)]
@ -73,11 +74,13 @@ impl Cid {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::repl::cid::Cid;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::time::Duration; use std::time::Duration;
use uuid::Uuid; use uuid::Uuid;
use crate::repl::cid::Cid;
#[test] #[test]
fn test_cid_ordering() { fn test_cid_ordering() {
// Check diff ts // Check diff ts

View file

@ -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::btree_map::Keys;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt; use std::fmt;
use std::ops::Bound; use std::ops::Bound;
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! { lazy_static! {
static ref PVCLASS_TOMBSTONE: PartialValue = PartialValue::new_class("tombstone"); static ref PVCLASS_TOMBSTONE: PartialValue = PartialValue::new_class("tombstone");
static ref PVCLASS_RECYCLED: PartialValue = PartialValue::new_class("recycled"); static ref PVCLASS_RECYCLED: PartialValue = PartialValue::new_class("recycled");
@ -518,12 +517,13 @@ impl EntryChangelog {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::time::Duration;
use crate::entry::Eattrs; use crate::entry::Eattrs;
// use crate::prelude::*; // use crate::prelude::*;
use crate::repl::cid::Cid; use crate::repl::cid::Cid;
use crate::repl::entry::{Change, EntryChangelog, State, Transition}; use crate::repl::entry::{Change, EntryChangelog, State, Transition};
use crate::schema::{Schema, SchemaTransaction}; use crate::schema::{Schema, SchemaTransaction};
use std::time::Duration;
#[test] #[test]
fn test_entrychangelog_basic() { fn test_entrychangelog_basic() {

View file

@ -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::cmp::Ordering;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ops::Bound::*; use std::ops::Bound::*;
use std::sync::Arc; 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 { pub struct ReplicationUpdateVector {
// This sorts by time. Should we look up by IDL or by UUID? // 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 // 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