mirror of
https://github.com/kanidm/kanidm.git
synced 2025-05-21 16:33:55 +02:00
Merge branch 'master' into 20250226-form-post
This commit is contained in:
commit
4d870b430f
.cargo
.github/workflows
Cargo.lockCargo.tomlbook/src
examples
libs
proto/src/internal
pykanidm
scripts
server
Dockerfilebuilder.sh
core/src
daemon
lib-macros
lib/src
testkit-macros
testkit
tools
unix_integration/resolver
11
.cargo/config.toml
Normal file
11
.cargo/config.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
# The default ld from glibc is impossibly slow and consumes huge amounts of
|
||||
# memory. We use lld by default which often is twice as fast for significantly
|
||||
# less ram consumption.
|
||||
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
linker = "clang"
|
||||
rustflags = ["-C", "link-arg=-fuse-ld=lld", "-Ctarget-cpu=native"]
|
||||
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "clang"
|
||||
rustflags = ["-C", "link-arg=-fuse-ld=lld", "-Ctarget-cpu=native"]
|
4
.github/workflows/rust_build.yml
vendored
4
.github/workflows/rust_build.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
|||
libsystemd-dev
|
||||
|
||||
- name: "Build the workspace"
|
||||
run: cargo build --workspace
|
||||
run: cargo build --locked --workspace
|
||||
- name: "Check disk space and size of target, then clean it"
|
||||
run: |
|
||||
df -h
|
||||
|
@ -89,7 +89,7 @@ jobs:
|
|||
libsystemd-dev
|
||||
|
||||
- name: "Build the workspace"
|
||||
run: cargo build --workspace
|
||||
run: cargo build --locked --workspace
|
||||
- name: "Check disk space and size of target, then clean it"
|
||||
run: |
|
||||
df -h
|
||||
|
|
2
.github/workflows/windows_build.yml
vendored
2
.github/workflows/windows_build.yml
vendored
|
@ -31,6 +31,6 @@ jobs:
|
|||
uses: mozilla-actions/sccache-action@v0.0.7
|
||||
with:
|
||||
version: "v0.4.2"
|
||||
- run: cargo build -p kanidm_client -p kanidm_tools --bin kanidm
|
||||
- run: cargo build --locked -p kanidm_client -p kanidm_tools --bin kanidm
|
||||
# yamllint disable-line rule:line-length
|
||||
- run: cargo test -p kanidm_client -p kanidm_tools
|
||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3247,7 +3247,6 @@ dependencies = [
|
|||
"escargot",
|
||||
"fantoccini",
|
||||
"futures",
|
||||
"http 1.2.0",
|
||||
"jsonschema",
|
||||
"kanidm_build_profiles",
|
||||
"kanidm_client",
|
||||
|
|
|
@ -241,6 +241,7 @@ reqwest = { version = "0.12.12", default-features = false, features = [
|
|||
"json",
|
||||
"gzip",
|
||||
"rustls-tls-native-roots",
|
||||
"rustls-tls-native-roots-no-provider",
|
||||
] }
|
||||
rusqlite = { version = "^0.28.0", features = ["array", "bundled"] }
|
||||
rustls = { version = "0.23.21", default-features = false, features = [
|
||||
|
|
|
@ -100,21 +100,16 @@ You will need [rustup](https://rustup.rs/) to install a Rust toolchain.
|
|||
|
||||
### SUSE / OpenSUSE
|
||||
|
||||
> NOTE: clang and lld are required to build Kanidm due to performance issues with GCC/ld
|
||||
|
||||
You will need to install rustup and our build dependencies with:
|
||||
|
||||
```bash
|
||||
zypper in rustup git libudev-devel sqlite3-devel libopenssl-3-devel libselinux-devel pam-devel systemd-devel tpm2-0-tss-devel
|
||||
zypper in rustup git libudev-devel sqlite3-devel libopenssl-3-devel libselinux-devel \
|
||||
pam-devel systemd-devel tpm2-0-tss-devel clang lld make sccache
|
||||
```
|
||||
|
||||
You can then use rustup to complete the setup of the toolchain.
|
||||
|
||||
In some cases you may need to build other vendored components, or use an alternate linker. In these
|
||||
cases we advise you to also install.
|
||||
|
||||
```bash
|
||||
zypper in clang lld make sccache
|
||||
```
|
||||
|
||||
You should also adjust your environment with:
|
||||
|
||||
```bash
|
||||
|
@ -123,25 +118,16 @@ export CC="sccache /usr/bin/clang"
|
|||
export CXX="sccache /usr/bin/clang++"
|
||||
```
|
||||
|
||||
And add the following to a cargo config of your choice (such as ~/.cargo/config), adjusting for cpu
|
||||
arch
|
||||
|
||||
```toml
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "clang"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-fuse-ld=lld",
|
||||
]
|
||||
```
|
||||
|
||||
### Fedora
|
||||
|
||||
> NOTE: clang and lld are required to build Kanidm due to performance issues with GCC/ld
|
||||
|
||||
You will need [rustup](https://rustup.rs/) to install a Rust toolchain.
|
||||
|
||||
You will also need some system libraries to build this:
|
||||
|
||||
```text
|
||||
systemd-devel sqlite-devel openssl-devel pam-devel
|
||||
systemd-devel sqlite-devel openssl-devel pam-devel clang lld
|
||||
```
|
||||
|
||||
Building the Web UI requires additional packages:
|
||||
|
@ -152,12 +138,14 @@ perl-FindBin perl-File-Compare
|
|||
|
||||
### Ubuntu
|
||||
|
||||
> NOTE: clang and lld are required to build Kanidm due to performance issues with GCC/ld
|
||||
|
||||
You need [rustup](https://rustup.rs/) to install a Rust toolchain.
|
||||
|
||||
You will also need some system libraries to build this, which can be installed by running:
|
||||
|
||||
```bash
|
||||
sudo apt-get install libudev-dev libssl-dev libsystemd-dev pkg-config libpam0g-dev
|
||||
sudo apt-get install libudev-dev libssl-dev libsystemd-dev pkg-config libpam0g-dev clang lld
|
||||
```
|
||||
|
||||
Tested with Ubuntu 20.04 and 22.04.
|
||||
|
|
|
@ -137,9 +137,9 @@ chmod 666 ~/.cache/kanidm_tokens
|
|||
docker pull kanidm/tools:latest
|
||||
docker run --rm -i -t \
|
||||
--network host \
|
||||
--mount "type=bind,src=/etc/kanidm/config,target=/etc/kanidm/config" \
|
||||
--mount "type=bind,src=$HOME/.config/kanidm,target=/home/kanidm/.config/kanidm" \
|
||||
--mount "type=bind,src=$HOME/.cache/kanidm_tokens,target=/home/kanidm/.cache/kanidm_tokens" \
|
||||
--mount "type=bind,src=/etc/kanidm/config,target=/data/config:ro" \
|
||||
--mount "type=bind,src=$HOME/.config/kanidm,target=/root/.config/kanidm" \
|
||||
--mount "type=bind,src=$HOME/.cache/kanidm_tokens,target=/root/.cache/kanidm_tokens" \
|
||||
kanidm/tools:latest \
|
||||
/sbin/kanidm --help
|
||||
```
|
||||
|
|
|
@ -147,8 +147,8 @@ Features or APIs may be removed with 1 release versions notice. Deprecations wil
|
|||
|
||||
### Python module
|
||||
|
||||
The python module will typically trail changes in functionality of the core Rust code, and will be
|
||||
developed as we it for our own needs - please feel free to add functionality or improvements, or
|
||||
The Python module will typically trail changes in functionality of the core Rust code, and has been
|
||||
developed as we have needed it - please feel free to add functionality or improvements, or
|
||||
[ask for them in a Github issue](http://github.com/kanidm/kanidm/issues/new/choose)!
|
||||
|
||||
All code changes will include full type-casting wherever possible.
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
# The configuration file version.
|
||||
version = '2'
|
||||
|
||||
# ⚠️ Ensure that you have the [kanidm] or other provider sections below
|
||||
# configured else accounts from remote sources will not be available.
|
||||
|
||||
# Kanidm unix will bind all cached credentials to a local Hardware Security
|
||||
# Module (HSM) to prevent exfiltration and attacks against these. In addition,
|
||||
# any internal private keys will also be stored in this HSM.
|
||||
|
@ -136,6 +139,7 @@ version = '2'
|
|||
# allow_local_account_override = ["admin"]
|
||||
|
||||
|
||||
# ========================================
|
||||
# This section enables the Kanidm provider
|
||||
[kanidm]
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ use std::time::Duration;
|
|||
|
||||
use compact_jwt::Jwk;
|
||||
|
||||
pub use http;
|
||||
use kanidm_proto::constants::uri::V1_AUTH_VALID;
|
||||
use kanidm_proto::constants::{
|
||||
ATTR_DOMAIN_DISPLAY_NAME, ATTR_DOMAIN_LDAP_BASEDN, ATTR_DOMAIN_SSID, ATTR_ENTRY_MANAGED_BY,
|
||||
|
@ -137,6 +138,7 @@ pub struct KanidmClientBuilder {
|
|||
use_system_proxies: bool,
|
||||
/// Where to store auth tokens, only use in testing!
|
||||
token_cache_path: Option<String>,
|
||||
disable_system_ca_store: bool,
|
||||
}
|
||||
|
||||
impl Display for KanidmClientBuilder {
|
||||
|
@ -170,33 +172,6 @@ impl Display for KanidmClientBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kanidmclientbuilder_display() {
|
||||
let defaultclient = KanidmClientBuilder::default();
|
||||
println!("{}", defaultclient);
|
||||
assert!(defaultclient.to_string().contains("verify_ca"));
|
||||
|
||||
let testclient = KanidmClientBuilder {
|
||||
address: Some("https://example.com".to_string()),
|
||||
verify_ca: true,
|
||||
verify_hostnames: true,
|
||||
ca: None,
|
||||
connect_timeout: Some(420),
|
||||
request_timeout: Some(69),
|
||||
use_system_proxies: true,
|
||||
token_cache_path: Some(CLIENT_TOKEN_CACHE.to_string()),
|
||||
};
|
||||
println!("testclient {}", testclient);
|
||||
assert!(testclient.to_string().contains("verify_ca: true"));
|
||||
assert!(testclient.to_string().contains("verify_hostnames: true"));
|
||||
|
||||
let badness = testclient.danger_accept_invalid_hostnames(true);
|
||||
let badness = badness.danger_accept_invalid_certs(true);
|
||||
println!("badness: {}", badness);
|
||||
assert!(badness.to_string().contains("verify_ca: false"));
|
||||
assert!(badness.to_string().contains("verify_hostnames: false"));
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KanidmClient {
|
||||
pub(crate) client: reqwest::Client,
|
||||
|
@ -233,6 +208,7 @@ impl KanidmClientBuilder {
|
|||
request_timeout: None,
|
||||
use_system_proxies: true,
|
||||
token_cache_path: None,
|
||||
disable_system_ca_store: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,6 +266,7 @@ impl KanidmClientBuilder {
|
|||
request_timeout,
|
||||
use_system_proxies,
|
||||
token_cache_path,
|
||||
disable_system_ca_store,
|
||||
} = self;
|
||||
// Process and apply all our options if they exist.
|
||||
let address = match kcc.uri {
|
||||
|
@ -316,6 +293,7 @@ impl KanidmClientBuilder {
|
|||
request_timeout,
|
||||
use_system_proxies,
|
||||
token_cache_path,
|
||||
disable_system_ca_store,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -416,6 +394,16 @@ impl KanidmClientBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Enable or disable the native ca roots. By default these roots are enabled.
|
||||
pub fn enable_native_ca_roots(self, enable: bool) -> Self {
|
||||
KanidmClientBuilder {
|
||||
// We have to flip the bool state here due to Default on bool being false
|
||||
// and we want our options to be positive to a native speaker.
|
||||
disable_system_ca_store: !enable,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostnames: bool) -> Self {
|
||||
KanidmClientBuilder {
|
||||
// We have to flip the bool state here due to english language.
|
||||
|
@ -527,6 +515,7 @@ impl KanidmClientBuilder {
|
|||
// implement sticky sessions with cookies.
|
||||
.cookie_store(true)
|
||||
.cookie_provider(client_cookies.clone())
|
||||
.tls_built_in_native_certs(!self.disable_system_ca_store)
|
||||
.danger_accept_invalid_hostnames(!self.verify_hostnames)
|
||||
.danger_accept_invalid_certs(!self.verify_ca);
|
||||
|
||||
|
@ -579,32 +568,6 @@ impl KanidmClientBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_make_url() {
|
||||
use kanidm_proto::constants::DEFAULT_SERVER_ADDRESS;
|
||||
let client: KanidmClient = KanidmClientBuilder::new()
|
||||
.address(format!("https://{}", DEFAULT_SERVER_ADDRESS))
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
client.get_url(),
|
||||
Url::parse(&format!("https://{}", DEFAULT_SERVER_ADDRESS)).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
client.make_url("/hello"),
|
||||
Url::parse(&format!("https://{}/hello", DEFAULT_SERVER_ADDRESS)).unwrap()
|
||||
);
|
||||
|
||||
let client: KanidmClient = KanidmClientBuilder::new()
|
||||
.address(format!("https://{}/cheese/", DEFAULT_SERVER_ADDRESS))
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
client.make_url("hello"),
|
||||
Url::parse(&format!("https://{}/cheese/hello", DEFAULT_SERVER_ADDRESS)).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
/// This is probably pretty jank but it works and was pulled from here:
|
||||
/// <https://github.com/seanmonstar/reqwest/issues/1602#issuecomment-1220996681>
|
||||
fn find_reqwest_error_source<E: std::error::Error + 'static>(
|
||||
|
@ -623,6 +586,11 @@ fn find_reqwest_error_source<E: std::error::Error + 'static>(
|
|||
}
|
||||
|
||||
impl KanidmClient {
|
||||
/// Access the underlying reqwest client that has been configured for this Kanidm server
|
||||
pub fn client(&self) -> &reqwest::Client {
|
||||
&self.client
|
||||
}
|
||||
|
||||
pub fn get_origin(&self) -> &Url {
|
||||
&self.origin
|
||||
}
|
||||
|
@ -2174,31 +2142,97 @@ impl KanidmClient {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_no_client_version_check_on_502() {
|
||||
let res = reqwest::Response::from(
|
||||
http::Response::builder()
|
||||
.status(StatusCode::GATEWAY_TIMEOUT)
|
||||
.body("")
|
||||
.unwrap(),
|
||||
);
|
||||
let client = KanidmClientBuilder::new()
|
||||
.address("http://localhost:8080".to_string())
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
eprintln!("This should pass because we are returning 504 and shouldn't check version...");
|
||||
client.expect_version(&res).await;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{KanidmClient, KanidmClientBuilder};
|
||||
use kanidm_proto::constants::CLIENT_TOKEN_CACHE;
|
||||
use reqwest::StatusCode;
|
||||
use url::Url;
|
||||
|
||||
let res = reqwest::Response::from(
|
||||
http::Response::builder()
|
||||
.status(StatusCode::BAD_GATEWAY)
|
||||
.body("")
|
||||
.unwrap(),
|
||||
);
|
||||
let client = KanidmClientBuilder::new()
|
||||
.address("http://localhost:8080".to_string())
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
eprintln!("This should pass because we are returning 502 and shouldn't check version...");
|
||||
client.expect_version(&res).await;
|
||||
#[tokio::test]
|
||||
async fn test_no_client_version_check_on_502() {
|
||||
let res = reqwest::Response::from(
|
||||
http::Response::builder()
|
||||
.status(StatusCode::GATEWAY_TIMEOUT)
|
||||
.body("")
|
||||
.unwrap(),
|
||||
);
|
||||
let client = KanidmClientBuilder::new()
|
||||
.address("http://localhost:8080".to_string())
|
||||
.enable_native_ca_roots(false)
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
eprintln!("This should pass because we are returning 504 and shouldn't check version...");
|
||||
client.expect_version(&res).await;
|
||||
|
||||
let res = reqwest::Response::from(
|
||||
http::Response::builder()
|
||||
.status(StatusCode::BAD_GATEWAY)
|
||||
.body("")
|
||||
.unwrap(),
|
||||
);
|
||||
let client = KanidmClientBuilder::new()
|
||||
.address("http://localhost:8080".to_string())
|
||||
.enable_native_ca_roots(false)
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
eprintln!("This should pass because we are returning 502 and shouldn't check version...");
|
||||
client.expect_version(&res).await;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_make_url() {
|
||||
use kanidm_proto::constants::DEFAULT_SERVER_ADDRESS;
|
||||
let client: KanidmClient = KanidmClientBuilder::new()
|
||||
.address(format!("https://{}", DEFAULT_SERVER_ADDRESS))
|
||||
.enable_native_ca_roots(false)
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
client.get_url(),
|
||||
Url::parse(&format!("https://{}", DEFAULT_SERVER_ADDRESS)).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
client.make_url("/hello"),
|
||||
Url::parse(&format!("https://{}/hello", DEFAULT_SERVER_ADDRESS)).unwrap()
|
||||
);
|
||||
|
||||
let client: KanidmClient = KanidmClientBuilder::new()
|
||||
.address(format!("https://{}/cheese/", DEFAULT_SERVER_ADDRESS))
|
||||
.enable_native_ca_roots(false)
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
client.make_url("hello"),
|
||||
Url::parse(&format!("https://{}/cheese/hello", DEFAULT_SERVER_ADDRESS)).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kanidmclientbuilder_display() {
|
||||
let defaultclient = KanidmClientBuilder::default();
|
||||
println!("{}", defaultclient);
|
||||
assert!(defaultclient.to_string().contains("verify_ca"));
|
||||
|
||||
let testclient = KanidmClientBuilder {
|
||||
address: Some("https://example.com".to_string()),
|
||||
verify_ca: true,
|
||||
verify_hostnames: true,
|
||||
ca: None,
|
||||
connect_timeout: Some(420),
|
||||
request_timeout: Some(69),
|
||||
use_system_proxies: true,
|
||||
token_cache_path: Some(CLIENT_TOKEN_CACHE.to_string()),
|
||||
disable_system_ca_store: false,
|
||||
};
|
||||
println!("testclient {}", testclient);
|
||||
assert!(testclient.to_string().contains("verify_ca: true"));
|
||||
assert!(testclient.to_string().contains("verify_hostnames: true"));
|
||||
|
||||
let badness = testclient.danger_accept_invalid_hostnames(true);
|
||||
let badness = badness.danger_accept_invalid_certs(true);
|
||||
println!("badness: {}", badness);
|
||||
assert!(badness.to_string().contains("verify_ca: false"));
|
||||
assert!(badness.to_string().contains("verify_hostnames: false"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ use std::os::macos::fs::MetadataExt;
|
|||
#[cfg(target_os = "illumos")]
|
||||
use std::os::illumos::fs::MetadataExt;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use std::os::android::fs::MetadataExt;
|
||||
|
||||
use kanidm_utils_users::{get_current_gid, get_current_uid};
|
||||
|
||||
use std::fmt;
|
||||
|
|
|
@ -222,6 +222,7 @@ pub enum OperationError {
|
|||
MG0006SKConstraintsNotMet,
|
||||
MG0007Oauth2StrictConstraintsNotMet,
|
||||
MG0008SkipUpgradeAttempted,
|
||||
MG0009InvalidTargetLevelForBootstrap,
|
||||
//
|
||||
KP0001KeyProviderNotLoaded,
|
||||
KP0002KeyProviderInvalidClass,
|
||||
|
@ -462,6 +463,7 @@ impl OperationError {
|
|||
Self::MG0006SKConstraintsNotMet => Some("Migration Constraints Not Met - Security Keys should not be present.".into()),
|
||||
Self::MG0007Oauth2StrictConstraintsNotMet => Some("Migration Constraints Not Met - All OAuth2 clients must have strict-redirect-uri mode enabled.".into()),
|
||||
Self::MG0008SkipUpgradeAttempted => Some("Skip Upgrade Attempted.".into()),
|
||||
Self::MG0009InvalidTargetLevelForBootstrap => Some("The request target domain level was not valid for bootstrapping a new server instance".into()),
|
||||
Self::PL0001GidOverlapsSystemRange => None,
|
||||
Self::SC0001IncomingSshPublicKey => None,
|
||||
Self::SC0002ReferenceSyntaxInvalid => Some("A SCIM Reference Set contained invalid syntax and can not be processed.".into()),
|
||||
|
|
362
pykanidm/poetry.lock
generated
362
pykanidm/poetry.lock
generated
|
@ -13,92 +13,92 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "aiohttp"
|
||||
version = "3.11.12"
|
||||
version = "3.11.13"
|
||||
description = "Async http client/server framework (asyncio)"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:584096938a001378484aa4ee54e05dc79c7b9dd933e271c744a97b3b6f644957"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392432a2dde22b86f70dd4a0e9671a349446c93965f261dbaecfaf28813e5c42"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d385b8e7f3a870146bf5ea31786ef7463e99eb59e31db56e2315535d811f55"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b10a47e5390c4b30a0d58ee12581003be52eedd506862ab7f97da7a66805befb"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5263dcede17b6b0c41ef0c3ccce847d82a7da98709e75cf7efde3e9e3b5cae"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50c5c7b8aa5443304c55c262c5693b108c35a3b61ef961f1e782dd52a2f559c7"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1c031a7572f62f66f1257db37ddab4cb98bfaf9b9434a3b4840bf3560f5e788"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e44eba534381dd2687be50cbd5f2daded21575242ecfdaf86bbeecbc38dae8e"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:145a73850926018ec1681e734cedcf2716d6a8697d90da11284043b745c286d5"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2c311e2f63e42c1bf86361d11e2c4a59f25d9e7aabdbdf53dc38b885c5435cdb"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ea756b5a7bac046d202a9a3889b9a92219f885481d78cd318db85b15cc0b7bcf"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:526c900397f3bbc2db9cb360ce9c35134c908961cdd0ac25b1ae6ffcaa2507ff"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-win32.whl", hash = "sha256:b8d3bb96c147b39c02d3db086899679f31958c5d81c494ef0fc9ef5bb1359b3d"},
|
||||
{file = "aiohttp-3.11.12-cp310-cp310-win_amd64.whl", hash = "sha256:7fe3d65279bfbee8de0fb4f8c17fc4e893eed2dba21b2f680e930cc2b09075c5"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-win32.whl", hash = "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16"},
|
||||
{file = "aiohttp-3.11.12-cp311-cp311-win_amd64.whl", hash = "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-win32.whl", hash = "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a"},
|
||||
{file = "aiohttp-3.11.12-cp312-cp312-win_amd64.whl", hash = "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-win32.whl", hash = "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f"},
|
||||
{file = "aiohttp-3.11.12-cp313-cp313-win_amd64.whl", hash = "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c3623053b85b4296cd3925eeb725e386644fd5bc67250b3bb08b0f144803e7b"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67453e603cea8e85ed566b2700efa1f6916aefbc0c9fcb2e86aaffc08ec38e78"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6130459189e61baac5a88c10019b21e1f0c6d00ebc770e9ce269475650ff7f73"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9060addfa4ff753b09392efe41e6af06ea5dd257829199747b9f15bfad819460"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34245498eeb9ae54c687a07ad7f160053911b5745e186afe2d0c0f2898a1ab8a"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8dc0fba9a74b471c45ca1a3cb6e6913ebfae416678d90529d188886278e7f3f6"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a478aa11b328983c4444dacb947d4513cb371cd323f3845e53caeda6be5589d5"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c160a04283c8c6f55b5bf6d4cad59bb9c5b9c9cd08903841b25f1f7109ef1259"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:edb69b9589324bdc40961cdf0657815df674f1743a8d5ad9ab56a99e4833cfdd"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ee84c2a22a809c4f868153b178fe59e71423e1f3d6a8cd416134bb231fbf6d3"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bf4480a5438f80e0f1539e15a7eb8b5f97a26fe087e9828e2c0ec2be119a9f72"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e6b2732ef3bafc759f653a98881b5b9cdef0716d98f013d376ee8dfd7285abf1"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f752e80606b132140883bb262a457c475d219d7163d996dc9072434ffb0784c4"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab3247d58b393bda5b1c8f31c9edece7162fc13265334217785518dd770792b8"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-win32.whl", hash = "sha256:0d5176f310a7fe6f65608213cc74f4228e4f4ce9fd10bcb2bb6da8fc66991462"},
|
||||
{file = "aiohttp-3.11.12-cp39-cp39-win_amd64.whl", hash = "sha256:74bd573dde27e58c760d9ca8615c41a57e719bff315c9adb6f2a4281a28e8798"},
|
||||
{file = "aiohttp-3.11.12.tar.gz", hash = "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4fe27dbbeec445e6e1291e61d61eb212ee9fed6e47998b27de71d70d3e8777d"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e64ca2dbea28807f8484c13f684a2f761e69ba2640ec49dacd342763cc265ef"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9840be675de208d1f68f84d578eaa4d1a36eee70b16ae31ab933520c49ba1325"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28a772757c9067e2aee8a6b2b425d0efaa628c264d6416d283694c3d86da7689"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b88aca5adbf4625e11118df45acac29616b425833c3be7a05ef63a6a4017bfdb"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce10ddfbe26ed5856d6902162f71b8fe08545380570a885b4ab56aecfdcb07f4"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa48dac27f41b36735c807d1ab093a8386701bbf00eb6b89a0f69d9fa26b3671"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89ce611b1eac93ce2ade68f1470889e0173d606de20c85a012bfa24be96cf867"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78e4dd9c34ec7b8b121854eb5342bac8b02aa03075ae8618b6210a06bbb8a115"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:66047eacbc73e6fe2462b77ce39fc170ab51235caf331e735eae91c95e6a11e4"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ad8f1c19fe277eeb8bc45741c6d60ddd11d705c12a4d8ee17546acff98e0802"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64815c6f02e8506b10113ddbc6b196f58dbef135751cc7c32136df27b736db09"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:967b93f21b426f23ca37329230d5bd122f25516ae2f24a9cea95a30023ff8283"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf1f31f83d16ec344136359001c5e871915c6ab685a3d8dee38e2961b4c81730"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-win32.whl", hash = "sha256:00c8ac69e259c60976aa2edae3f13d9991cf079aaa4d3cd5a49168ae3748dee3"},
|
||||
{file = "aiohttp-3.11.13-cp310-cp310-win_amd64.whl", hash = "sha256:90d571c98d19a8b6e793b34aa4df4cee1e8fe2862d65cc49185a3a3d0a1a3996"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b35aab22419ba45f8fc290d0010898de7a6ad131e468ffa3922b1b0b24e9d2e"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81cba651db8795f688c589dd11a4fbb834f2e59bbf9bb50908be36e416dc760"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f55d0f242c2d1fcdf802c8fabcff25a9d85550a4cf3a9cf5f2a6b5742c992839"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4bea08a6aad9195ac9b1be6b0c7e8a702a9cec57ce6b713698b4a5afa9c2e33"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6070bcf2173a7146bb9e4735b3c62b2accba459a6eae44deea0eb23e0035a23"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:718d5deb678bc4b9d575bfe83a59270861417da071ab44542d0fcb6faa686636"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f6b2c5b4a4d22b8fb2c92ac98e0747f5f195e8e9448bfb7404cd77e7bfa243f"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747ec46290107a490d21fe1ff4183bef8022b848cf9516970cb31de6d9460088"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:01816f07c9cc9d80f858615b1365f8319d6a5fd079cd668cc58e15aafbc76a54"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a08ad95fcbd595803e0c4280671d808eb170a64ca3f2980dd38e7a72ed8d1fea"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c97be90d70f7db3aa041d720bfb95f4869d6063fcdf2bb8333764d97e319b7d0"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ab915a57c65f7a29353c8014ac4be685c8e4a19e792a79fe133a8e101111438e"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:35cda4e07f5e058a723436c4d2b7ba2124ab4e0aa49e6325aed5896507a8a42e"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:af55314407714fe77a68a9ccaab90fdb5deb57342585fd4a3a8102b6d4370080"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-win32.whl", hash = "sha256:42d689a5c0a0c357018993e471893e939f555e302313d5c61dfc566c2cad6185"},
|
||||
{file = "aiohttp-3.11.13-cp311-cp311-win_amd64.whl", hash = "sha256:b73a2b139782a07658fbf170fe4bcdf70fc597fae5ffe75e5b67674c27434a9f"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2eabb269dc3852537d57589b36d7f7362e57d1ece308842ef44d9830d2dc3c90"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b77ee42addbb1c36d35aca55e8cc6d0958f8419e458bb70888d8c69a4ca833d"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55789e93c5ed71832e7fac868167276beadf9877b85697020c46e9a75471f55f"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c929f9a7249a11e4aa5c157091cfad7f49cc6b13f4eecf9b747104befd9f56f2"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d33851d85537bbf0f6291ddc97926a754c8f041af759e0aa0230fe939168852b"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9229d8613bd8401182868fe95688f7581673e1c18ff78855671a4b8284f47bcb"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669dd33f028e54fe4c96576f406ebb242ba534dd3a981ce009961bf49960f117"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1b20a1ace54af7db1f95af85da530fe97407d9063b7aaf9ce6a32f44730778"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5724cc77f4e648362ebbb49bdecb9e2b86d9b172c68a295263fa072e679ee69d"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa36c35e94ecdb478246dd60db12aba57cfcd0abcad43c927a8876f25734d496"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9b5b37c863ad5b0892cc7a4ceb1e435e5e6acd3f2f8d3e11fa56f08d3c67b820"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e06cf4852ce8c4442a59bae5a3ea01162b8fcb49ab438d8548b8dc79375dad8a"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5194143927e494616e335d074e77a5dac7cd353a04755330c9adc984ac5a628e"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afcb6b275c2d2ba5d8418bf30a9654fa978b4f819c2e8db6311b3525c86fe637"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-win32.whl", hash = "sha256:7104d5b3943c6351d1ad7027d90bdd0ea002903e9f610735ac99df3b81f102ee"},
|
||||
{file = "aiohttp-3.11.13-cp312-cp312-win_amd64.whl", hash = "sha256:47dc018b1b220c48089b5b9382fbab94db35bef2fa192995be22cbad3c5730c8"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9862d077b9ffa015dbe3ce6c081bdf35135948cb89116e26667dd183550833d1"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbfef0666ae9e07abfa2c54c212ac18a1f63e13e0760a769f70b5717742f3ece"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a1f7d857c4fcf7cabb1178058182c789b30d85de379e04f64c15b7e88d66fb"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba40b7ae0f81c7029583a338853f6607b6d83a341a3dcde8bed1ea58a3af1df9"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5b95787335c483cd5f29577f42bbe027a412c5431f2f80a749c80d040f7ca9f"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d474c5c1f0b9405c1565fafdc4429fa7d986ccbec7ce55bc6a330f36409cad"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e83fb1991e9d8982b3b36aea1e7ad27ea0ce18c14d054c7a404d68b0319eebb"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4586a68730bd2f2b04a83e83f79d271d8ed13763f64b75920f18a3a677b9a7f0"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fe4eb0e7f50cdb99b26250d9328faef30b1175a5dbcfd6d0578d18456bac567"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a8a6bc19818ac3e5596310ace5aa50d918e1ebdcc204dc96e2f4d505d51740c"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f27eec42f6c3c1df09cfc1f6786308f8b525b8efaaf6d6bd76c1f52c6511f6a"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a4a13dfbb23977a51853b419141cd0a9b9573ab8d3a1455c6e63561387b52ff"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:02876bf2f69b062584965507b07bc06903c2dc93c57a554b64e012d636952654"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b992778d95b60a21c4d8d4a5f15aaab2bd3c3e16466a72d7f9bfd86e8cea0d4b"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-win32.whl", hash = "sha256:507ab05d90586dacb4f26a001c3abf912eb719d05635cbfad930bdbeb469b36c"},
|
||||
{file = "aiohttp-3.11.13-cp313-cp313-win_amd64.whl", hash = "sha256:5ceb81a4db2decdfa087381b5fc5847aa448244f973e5da232610304e199e7b2"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:51c3ff9c7a25f3cad5c09d9aacbc5aefb9267167c4652c1eb737989b554fe278"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e271beb2b1dabec5cd84eb488bdabf9758d22ad13471e9c356be07ad139b3012"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e9eb7e5764abcb49f0e2bd8f5731849b8728efbf26d0cac8e81384c95acec3f"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baae005092e3f200de02699314ac8933ec20abf998ec0be39448f6605bce93df"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1982c98ac62c132d2b773d50e2fcc941eb0b8bad3ec078ce7e7877c4d5a2dce7"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2b25b2eeb35707113b2d570cadc7c612a57f1c5d3e7bb2b13870fe284e08fc0"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b27961d65639128336b7a7c3f0046dcc62a9443d5ef962e3c84170ac620cec47"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe9f1e05025eacdd97590895e2737b9f851d0eb2e017ae9574d9a4f0b6252"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa1fb1b61881c8405829c50e9cc5c875bfdbf685edf57a76817dfb50643e4a1a"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:25de43bb3cf83ad83efc8295af7310219af6dbe4c543c2e74988d8e9c8a2a917"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe7065e2215e4bba63dc00db9ae654c1ba3950a5fff691475a32f511142fcddb"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7836587eef675a17d835ec3d98a8c9acdbeb2c1d72b0556f0edf4e855a25e9c1"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:85fa0b18558eb1427090912bd456a01f71edab0872f4e0f9e4285571941e4090"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a86dc177eb4c286c19d1823ac296299f59ed8106c9536d2b559f65836e0fb2c6"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-win32.whl", hash = "sha256:684eea71ab6e8ade86b9021bb62af4bf0881f6be4e926b6b5455de74e420783a"},
|
||||
{file = "aiohttp-3.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:82c249f2bfa5ecbe4a1a7902c81c0fba52ed9ebd0176ab3047395d02ad96cfcb"},
|
||||
{file = "aiohttp-3.11.13.tar.gz", hash = "sha256:8ce789231404ca8fff7f693cdce398abf6d90fd5dae2b1847477196c243b1fbb"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -185,13 +185,13 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
|
|||
|
||||
[[package]]
|
||||
name = "authlib"
|
||||
version = "1.4.1"
|
||||
version = "1.5.1"
|
||||
description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "Authlib-1.4.1-py2.py3-none-any.whl", hash = "sha256:edc29c3f6a3e72cd9e9f45fff67fc663a2c364022eb0371c003f22d5405915c1"},
|
||||
{file = "authlib-1.4.1.tar.gz", hash = "sha256:30ead9ea4993cdbab821dc6e01e818362f92da290c04c7f6a1940f86507a790d"},
|
||||
{file = "authlib-1.5.1-py2.py3-none-any.whl", hash = "sha256:8408861cbd9b4ea2ff759b00b6f02fd7d81ac5a56d0b2b22c08606c6049aae11"},
|
||||
{file = "authlib-1.5.1.tar.gz", hash = "sha256:5cbc85ecb0667312c1cdc2f9095680bb735883b123fb509fde1e65b1c5df972e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -211,6 +211,24 @@ files = [
|
|||
[package.extras]
|
||||
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "backrefs"
|
||||
version = "5.8"
|
||||
description = "A wrapper around re and regex that adds additional back references."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "backrefs-5.8-py310-none-any.whl", hash = "sha256:c67f6638a34a5b8730812f5101376f9d41dc38c43f1fdc35cb54700f6ed4465d"},
|
||||
{file = "backrefs-5.8-py311-none-any.whl", hash = "sha256:2e1c15e4af0e12e45c8701bd5da0902d326b2e200cafcd25e49d9f06d44bb61b"},
|
||||
{file = "backrefs-5.8-py312-none-any.whl", hash = "sha256:bbef7169a33811080d67cdf1538c8289f76f0942ff971222a16034da88a73486"},
|
||||
{file = "backrefs-5.8-py313-none-any.whl", hash = "sha256:e3a63b073867dbefd0536425f43db618578528e3896fb77be7141328642a1585"},
|
||||
{file = "backrefs-5.8-py39-none-any.whl", hash = "sha256:a66851e4533fb5b371aa0628e1fee1af05135616b86140c9d787a2ffdf4b8fdc"},
|
||||
{file = "backrefs-5.8.tar.gz", hash = "sha256:2cab642a205ce966af3dd4b38ee36009b31fa9502a35fd61d59ccc116e40a6bd"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
extras = ["regex"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.8.30"
|
||||
|
@ -959,13 +977,13 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp
|
|||
|
||||
[[package]]
|
||||
name = "mkdocs-autorefs"
|
||||
version = "1.3.0"
|
||||
version = "1.4.0"
|
||||
description = "Automatically link across pages in MkDocs."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "mkdocs_autorefs-1.3.0-py3-none-any.whl", hash = "sha256:d180f9778a04e78b7134e31418f238bba56f56d6a8af97873946ff661befffb3"},
|
||||
{file = "mkdocs_autorefs-1.3.0.tar.gz", hash = "sha256:6867764c099ace9025d6ac24fd07b85a98335fbd30107ef01053697c8f46db61"},
|
||||
{file = "mkdocs_autorefs-1.4.0-py3-none-any.whl", hash = "sha256:bad19f69655878d20194acd0162e29a89c3f7e6365ffe54e72aa3fd1072f240d"},
|
||||
{file = "mkdocs_autorefs-1.4.0.tar.gz", hash = "sha256:a9c0aa9c90edbce302c09d050a3c4cb7c76f8b7b2c98f84a7a05f53d00392156"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -992,17 +1010,18 @@ pyyaml = ">=5.1"
|
|||
|
||||
[[package]]
|
||||
name = "mkdocs-material"
|
||||
version = "9.6.5"
|
||||
version = "9.6.6"
|
||||
description = "Documentation that simply works"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "mkdocs_material-9.6.5-py3-none-any.whl", hash = "sha256:aad3e6fb860c20870f75fb2a69ef901f1be727891e41adb60b753efcae19453b"},
|
||||
{file = "mkdocs_material-9.6.5.tar.gz", hash = "sha256:b714679a8c91b0ffe2188e11ed58c44d2523e9c2ae26a29cc652fa7478faa21f"},
|
||||
{file = "mkdocs_material-9.6.6-py3-none-any.whl", hash = "sha256:904c422ec86086144495831cee2614bb8a0092572ef579af6392b8080309d3a3"},
|
||||
{file = "mkdocs_material-9.6.6.tar.gz", hash = "sha256:06141bd720b0b235829bd59e8afc11d5587c35ae7fc340612d2b3f554e6a69d8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
babel = ">=2.10,<3.0"
|
||||
backrefs = ">=5.7.post1,<6.0"
|
||||
colorama = ">=0.4,<1.0"
|
||||
jinja2 = ">=3.0,<4.0"
|
||||
markdown = ">=3.2,<4.0"
|
||||
|
@ -1011,7 +1030,6 @@ mkdocs-material-extensions = ">=1.3,<2.0"
|
|||
paginate = ">=0.5,<1.0"
|
||||
pygments = ">=2.16,<3.0"
|
||||
pymdown-extensions = ">=10.2,<11.0"
|
||||
regex = ">=2022.4"
|
||||
requests = ">=2.26,<3.0"
|
||||
|
||||
[package.extras]
|
||||
|
@ -1032,13 +1050,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "mkdocstrings"
|
||||
version = "0.28.1"
|
||||
version = "0.28.2"
|
||||
description = "Automatic documentation from sources, for MkDocs."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "mkdocstrings-0.28.1-py3-none-any.whl", hash = "sha256:a5878ae5cd1e26f491ff084c1f9ab995687d52d39a5c558e9b7023d0e4e0b740"},
|
||||
{file = "mkdocstrings-0.28.1.tar.gz", hash = "sha256:fb64576906771b7701e8e962fd90073650ff689e95eb86e86751a66d65ab4489"},
|
||||
{file = "mkdocstrings-0.28.2-py3-none-any.whl", hash = "sha256:57f79c557e2718d217d6f6a81bf75a0de097f10e922e7e5e00f085c3f0ff6895"},
|
||||
{file = "mkdocstrings-0.28.2.tar.gz", hash = "sha256:9b847266d7a588ea76a8385eaebe1538278b4361c0d1ce48ed005be59f053569"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1047,7 +1065,7 @@ Jinja2 = ">=2.11.1"
|
|||
Markdown = ">=3.6"
|
||||
MarkupSafe = ">=1.1"
|
||||
mkdocs = ">=1.4"
|
||||
mkdocs-autorefs = ">=1.3"
|
||||
mkdocs-autorefs = ">=1.4"
|
||||
mkdocs-get-deps = ">=0.2"
|
||||
pymdown-extensions = ">=6.3"
|
||||
typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""}
|
||||
|
@ -1059,19 +1077,19 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
|
|||
|
||||
[[package]]
|
||||
name = "mkdocstrings-python"
|
||||
version = "1.16.1"
|
||||
version = "1.16.2"
|
||||
description = "A Python handler for mkdocstrings."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "mkdocstrings_python-1.16.1-py3-none-any.whl", hash = "sha256:b88ff6fc6a293cee9cb42313f1cba37a2c5cdf37bcc60b241ec7ab66b5d41b58"},
|
||||
{file = "mkdocstrings_python-1.16.1.tar.gz", hash = "sha256:d7152d17da74d3616a0f17df5d2da771ecf7340518c158650e5a64a0a95973f4"},
|
||||
{file = "mkdocstrings_python-1.16.2-py3-none-any.whl", hash = "sha256:ff7e719404e59ad1a72f1afbe854769984c889b8fa043c160f6c988e1ad9e966"},
|
||||
{file = "mkdocstrings_python-1.16.2.tar.gz", hash = "sha256:942ec1a2e0481d28f96f93be3d6e343cab92a21e5baf01c37dd2d7236c4d0bd7"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
griffe = ">=0.49"
|
||||
mkdocs-autorefs = ">=1.2"
|
||||
mkdocstrings = ">=0.28"
|
||||
mkdocs-autorefs = ">=1.4"
|
||||
mkdocstrings = ">=0.28.2"
|
||||
typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[[package]]
|
||||
|
@ -1678,13 +1696,13 @@ extra = ["pygments (>=2.12)"]
|
|||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.3.4"
|
||||
version = "8.3.5"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
|
||||
{file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
|
||||
{file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"},
|
||||
{file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1857,94 +1875,6 @@ files = [
|
|||
attrs = ">=22.2.0"
|
||||
rpds-py = ">=0.7.0"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2024.7.24"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-win32.whl", hash = "sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66"},
|
||||
{file = "regex-2024.7.24-cp310-cp310-win_amd64.whl", hash = "sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-win32.whl", hash = "sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c"},
|
||||
{file = "regex-2024.7.24-cp311-cp311-win_amd64.whl", hash = "sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"},
|
||||
{file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-win32.whl", hash = "sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96"},
|
||||
{file = "regex-2024.7.24-cp38-cp38-win_amd64.whl", hash = "sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-win32.whl", hash = "sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1"},
|
||||
{file = "regex-2024.7.24-cp39-cp39-win_amd64.whl", hash = "sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9"},
|
||||
{file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
|
@ -2080,29 +2010,29 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.9.7"
|
||||
version = "0.9.9"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.9.7-py3-none-linux_armv6l.whl", hash = "sha256:99d50def47305fe6f233eb8dabfd60047578ca87c9dcb235c9723ab1175180f4"},
|
||||
{file = "ruff-0.9.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d59105ae9c44152c3d40a9c40d6331a7acd1cdf5ef404fbe31178a77b174ea66"},
|
||||
{file = "ruff-0.9.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f313b5800483770bd540cddac7c90fc46f895f427b7820f18fe1822697f1fec9"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:042ae32b41343888f59c0a4148f103208bf6b21c90118d51dc93a68366f4e903"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87862589373b33cc484b10831004e5e5ec47dc10d2b41ba770e837d4f429d721"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a17e1e01bee0926d351a1ee9bc15c445beae888f90069a6192a07a84af544b6b"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7c1f880ac5b2cbebd58b8ebde57069a374865c73f3bf41f05fe7a179c1c8ef22"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e63fc20143c291cab2841dbb8260e96bafbe1ba13fd3d60d28be2c71e312da49"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91ff963baed3e9a6a4eba2a02f4ca8eaa6eba1cc0521aec0987da8d62f53cbef"},
|
||||
{file = "ruff-0.9.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88362e3227c82f63eaebf0b2eff5b88990280fb1ecf7105523883ba8c3aaf6fb"},
|
||||
{file = "ruff-0.9.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0372c5a90349f00212270421fe91874b866fd3626eb3b397ede06cd385f6f7e0"},
|
||||
{file = "ruff-0.9.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d76b8ab60e99e6424cd9d3d923274a1324aefce04f8ea537136b8398bbae0a62"},
|
||||
{file = "ruff-0.9.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0c439bdfc8983e1336577f00e09a4e7a78944fe01e4ea7fe616d00c3ec69a3d0"},
|
||||
{file = "ruff-0.9.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:115d1f15e8fdd445a7b4dc9a30abae22de3f6bcabeb503964904471691ef7606"},
|
||||
{file = "ruff-0.9.7-py3-none-win32.whl", hash = "sha256:e9ece95b7de5923cbf38893f066ed2872be2f2f477ba94f826c8defdd6ec6b7d"},
|
||||
{file = "ruff-0.9.7-py3-none-win_amd64.whl", hash = "sha256:3770fe52b9d691a15f0b87ada29c45324b2ace8f01200fb0c14845e499eb0c2c"},
|
||||
{file = "ruff-0.9.7-py3-none-win_arm64.whl", hash = "sha256:b075a700b2533feb7a01130ff656a4ec0d5f340bb540ad98759b8401c32c2037"},
|
||||
{file = "ruff-0.9.7.tar.gz", hash = "sha256:643757633417907510157b206e490c3aa11cab0c087c912f60e07fbafa87a4c6"},
|
||||
{file = "ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367"},
|
||||
{file = "ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7"},
|
||||
{file = "ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb"},
|
||||
{file = "ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0"},
|
||||
{file = "ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17"},
|
||||
{file = "ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1"},
|
||||
{file = "ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57"},
|
||||
{file = "ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e"},
|
||||
{file = "ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1"},
|
||||
{file = "ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1"},
|
||||
{file = "ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf"},
|
||||
{file = "ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2151,13 +2081,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "types-requests"
|
||||
version = "2.32.0.20241016"
|
||||
version = "2.32.0.20250301"
|
||||
description = "Typing stubs for requests"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"},
|
||||
{file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"},
|
||||
{file = "types_requests-2.32.0.20250301-py3-none-any.whl", hash = "sha256:0003e0124e2cbefefb88222ff822b48616af40c74df83350f599a650c8de483b"},
|
||||
{file = "types_requests-2.32.0.20250301.tar.gz", hash = "sha256:3d909dc4eaab159c0d964ebe8bfa326a7afb4578d8706408d417e17d61b0c500"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -2373,4 +2303,4 @@ type = ["pytest-mypy"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "72e84e903994ae033467c589c6506cc54fc9c3075df75795b4d0f748ff91dfeb"
|
||||
content-hash = "5e5caa373faaad974b6688bbbce04f8d9d15f55b2b7f3b184ac456453742e2e3"
|
||||
|
|
|
@ -29,7 +29,7 @@ Authlib = "^1.2.0"
|
|||
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
ruff = ">=0.5.1,<0.9.8"
|
||||
ruff = ">=0.5.1,<0.9.10"
|
||||
pytest = "^8.3.4"
|
||||
mypy = "^1.14.1"
|
||||
types-requests = "^2.32.0.20241016"
|
||||
|
|
|
@ -11,7 +11,7 @@ WAIT_TIMER=5
|
|||
|
||||
|
||||
echo "Building release binaries..."
|
||||
cargo build --release --bin kanidm --bin kanidmd
|
||||
cargo build --locked --release --bin kanidm --bin kanidmd
|
||||
|
||||
if [ -d '.git' ]; then
|
||||
echo "You're in the root dir, let's move you!"
|
||||
|
|
|
@ -48,7 +48,7 @@ RUN --mount=type=cache,id=cargo,target=/cargo \
|
|||
export SCCACHE_DIR=/sccache && \
|
||||
export RUSTC_WRAPPER=/usr/bin/sccache && \
|
||||
export CC="/usr/bin/clang" && \
|
||||
cargo build -p daemon ${KANIDM_BUILD_OPTIONS} \
|
||||
cargo build --locked -p daemon ${KANIDM_BUILD_OPTIONS} \
|
||||
--target-dir="/usr/src/kanidm/target/" \
|
||||
--features="${KANIDM_FEATURES}" \
|
||||
--release; \
|
||||
|
|
|
@ -20,7 +20,7 @@ echo $RUSTC_WRAPPER && \
|
|||
echo $RUSTFLAGS && \
|
||||
echo $CC && \
|
||||
cargo build \
|
||||
--offline \
|
||||
--frozen \
|
||||
--features=concread/simd_support,libsqlite3-sys/bundled \
|
||||
--release; \
|
||||
if [ "${SCCACHE_REDIS}" != "" ]; \
|
||||
|
|
|
@ -115,9 +115,9 @@ async fn setup_qs_idms(
|
|||
.await?;
|
||||
|
||||
// We generate a SINGLE idms only!
|
||||
|
||||
let is_integration_test = config.integration_test_config.is_some();
|
||||
let (idms, idms_delayed, idms_audit) =
|
||||
IdmServer::new(query_server.clone(), &config.origin).await?;
|
||||
IdmServer::new(query_server.clone(), &config.origin, is_integration_test).await?;
|
||||
|
||||
Ok((query_server, idms, idms_delayed, idms_audit))
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ repository = { workspace = true }
|
|||
[[bin]]
|
||||
name = "kanidmd"
|
||||
path = "src/main.rs"
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ repository = { workspace = true }
|
|||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -18,7 +18,8 @@ use crate::be::idl_sqlite::{
|
|||
IdlSqlite, IdlSqliteReadTransaction, IdlSqliteTransaction, IdlSqliteWriteTransaction,
|
||||
};
|
||||
use crate::be::idxkey::{
|
||||
IdlCacheKey, IdlCacheKeyRef, IdlCacheKeyToRef, IdxKey, IdxKeyRef, IdxKeyToRef, IdxSlope,
|
||||
IdlCacheKey, IdlCacheKeyRef, IdlCacheKeyToRef, IdxKey, IdxKeyRef, IdxKeyToRef, IdxNameKey,
|
||||
IdxSlope,
|
||||
};
|
||||
use crate::be::keystorage::{KeyHandle, KeyHandleId};
|
||||
use crate::be::{BackendConfig, IdList, IdRawEntry};
|
||||
|
@ -35,6 +36,10 @@ const DEFAULT_NAME_CACHE_RATIO: usize = 8;
|
|||
const DEFAULT_CACHE_RMISS: usize = 0;
|
||||
const DEFAULT_CACHE_WMISS: usize = 0;
|
||||
|
||||
const DEFAULT_IDX_CACHE_RMISS: usize = 8;
|
||||
const DEFAULT_IDX_CACHE_WMISS: usize = 16;
|
||||
const DEFAULT_IDX_EXISTS_TARGET: usize = 256;
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
enum NameCacheKey {
|
||||
Name2Uuid(String),
|
||||
|
@ -55,6 +60,9 @@ pub struct IdlArcSqlite {
|
|||
entry_cache: ARCache<u64, Arc<EntrySealedCommitted>>,
|
||||
idl_cache: ARCache<IdlCacheKey, Box<IDLBitRange>>,
|
||||
name_cache: ARCache<NameCacheKey, NameCacheValue>,
|
||||
|
||||
idx_exists_cache: ARCache<IdxNameKey, bool>,
|
||||
|
||||
op_ts_max: CowCell<Option<Duration>>,
|
||||
allids: CowCell<IDLBitRange>,
|
||||
maxid: CowCell<u64>,
|
||||
|
@ -66,6 +74,8 @@ pub struct IdlArcSqliteReadTransaction<'a> {
|
|||
entry_cache: ARCacheReadTxn<'a, u64, Arc<EntrySealedCommitted>, ()>,
|
||||
idl_cache: ARCacheReadTxn<'a, IdlCacheKey, Box<IDLBitRange>, ()>,
|
||||
name_cache: ARCacheReadTxn<'a, NameCacheKey, NameCacheValue, ()>,
|
||||
|
||||
idx_exists_cache: ARCacheReadTxn<'a, IdxNameKey, bool, ()>,
|
||||
allids: CowCellReadTxn<IDLBitRange>,
|
||||
}
|
||||
|
||||
|
@ -74,6 +84,9 @@ pub struct IdlArcSqliteWriteTransaction<'a> {
|
|||
entry_cache: ARCacheWriteTxn<'a, u64, Arc<EntrySealedCommitted>, ()>,
|
||||
idl_cache: ARCacheWriteTxn<'a, IdlCacheKey, Box<IDLBitRange>, ()>,
|
||||
name_cache: ARCacheWriteTxn<'a, NameCacheKey, NameCacheValue, ()>,
|
||||
|
||||
idx_exists_cache: ARCacheWriteTxn<'a, IdxNameKey, bool, ()>,
|
||||
|
||||
op_ts_max: CowCellWriteTxn<'a, Option<Duration>>,
|
||||
allids: CowCellWriteTxn<'a, IDLBitRange>,
|
||||
maxid: CowCellWriteTxn<'a, u64>,
|
||||
|
@ -178,8 +191,8 @@ macro_rules! get_idl {
|
|||
// or smaller type. Perhaps even a small cache of the IdlCacheKeys that
|
||||
// are allocated to reduce some allocs? Probably over thinking it at
|
||||
// this point.
|
||||
//
|
||||
// First attempt to get from this cache.
|
||||
|
||||
// Now attempt to get from this cache.
|
||||
let cache_key = IdlCacheKeyRef {
|
||||
a: $attr,
|
||||
i: $itype,
|
||||
|
@ -195,16 +208,47 @@ macro_rules! get_idl {
|
|||
);
|
||||
return Ok(Some(data.as_ref().clone()));
|
||||
}
|
||||
|
||||
// If it was a miss, does the actually exist in the DB?
|
||||
let idx_key = IdxNameKey {
|
||||
a: $attr.clone(),
|
||||
i: $itype,
|
||||
};
|
||||
let idx_r = $self.idx_exists_cache.get(&idx_key);
|
||||
if idx_r == Some(&false) {
|
||||
// The idx does not exist - bail early.
|
||||
return Ok(None)
|
||||
}
|
||||
|
||||
// The table either exists and we don't have data on it yet,
|
||||
// or it does not exist and we need to hear back from the lower level
|
||||
|
||||
// If miss, get from db *and* insert to the cache.
|
||||
let db_r = $self.db.get_idl($attr, $itype, $idx_key)?;
|
||||
|
||||
if let Some(ref idl) = db_r {
|
||||
if idx_r == None {
|
||||
// It exists, so track that data, because we weren't
|
||||
// previously tracking it.
|
||||
$self.idx_exists_cache.insert(idx_key, true)
|
||||
}
|
||||
|
||||
let ncache_key = IdlCacheKey {
|
||||
a: $attr.clone(),
|
||||
i: $itype.clone(),
|
||||
k: $idx_key.into(),
|
||||
};
|
||||
$self.idl_cache.insert(ncache_key, Box::new(idl.clone()))
|
||||
}
|
||||
} else {
|
||||
// The DB was unable to return this idx because table backing the
|
||||
// idx does not exist. We should cache this to prevent repeat hits
|
||||
// on sqlite until the db does exist, at which point the cache is
|
||||
// cleared anyway.
|
||||
//
|
||||
// NOTE: If the db idx misses it returns Some(empty_set), so this
|
||||
// only caches missing index tables.
|
||||
$self.idx_exists_cache.insert(idx_key, false)
|
||||
};
|
||||
Ok(db_r)
|
||||
}};
|
||||
}
|
||||
|
@ -593,6 +637,7 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
*/
|
||||
self.entry_cache.clear();
|
||||
self.idl_cache.clear();
|
||||
self.idx_exists_cache.clear();
|
||||
self.name_cache.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
@ -604,6 +649,7 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
mut entry_cache,
|
||||
mut idl_cache,
|
||||
mut name_cache,
|
||||
idx_exists_cache,
|
||||
op_ts_max,
|
||||
allids,
|
||||
maxid,
|
||||
|
@ -677,6 +723,7 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
// Can no longer fail from this point.
|
||||
op_ts_max.commit();
|
||||
name_cache.commit();
|
||||
idx_exists_cache.commit();
|
||||
idl_cache.commit();
|
||||
allids.commit();
|
||||
maxid.commit();
|
||||
|
@ -708,6 +755,7 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
*self.maxid = mid;
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub fn write_identries<'b, I>(&'b mut self, mut entries: I) -> Result<(), OperationError>
|
||||
where
|
||||
I: Iterator<Item = &'b Entry<EntrySealed, EntryCommitted>>,
|
||||
|
@ -757,6 +805,7 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub fn write_idl(
|
||||
&mut self,
|
||||
attr: &Attribute,
|
||||
|
@ -1127,9 +1176,17 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_idx(&self, attr: &Attribute, itype: IndexType) -> Result<(), OperationError> {
|
||||
// We don't need to affect this, so pass it down.
|
||||
self.db.create_idx(attr, itype)
|
||||
pub fn create_idx(&mut self, attr: &Attribute, itype: IndexType) -> Result<(), OperationError> {
|
||||
self.db.create_idx(attr, itype)?;
|
||||
|
||||
// Cache that this exists since we just made it.
|
||||
let idx_key = IdxNameKey {
|
||||
a: attr.clone(),
|
||||
i: itype,
|
||||
};
|
||||
self.idx_exists_cache.insert(idx_key, true);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ⚠️ - This function will destroy all indexes in the database.
|
||||
|
@ -1141,6 +1198,7 @@ impl IdlArcSqliteWriteTransaction<'_> {
|
|||
debug!("CLEARING CACHE");
|
||||
self.db.danger_purge_idxs().map(|()| {
|
||||
self.idl_cache.clear();
|
||||
self.idx_exists_cache.clear();
|
||||
self.name_cache.clear();
|
||||
})
|
||||
}
|
||||
|
@ -1266,6 +1324,21 @@ impl IdlArcSqlite {
|
|||
OperationError::InvalidState
|
||||
})?;
|
||||
|
||||
let idx_exists_cache = ARCacheBuilder::new()
|
||||
.set_expected_workload(
|
||||
DEFAULT_IDX_EXISTS_TARGET,
|
||||
cfg.pool_size as usize,
|
||||
DEFAULT_IDX_CACHE_RMISS,
|
||||
DEFAULT_IDX_CACHE_WMISS,
|
||||
true,
|
||||
)
|
||||
.set_reader_quiesce(true)
|
||||
.build()
|
||||
.ok_or_else(|| {
|
||||
admin_error!("Failed to construct idx_exists_cache");
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
|
||||
let allids = CowCell::new(IDLBitRange::new());
|
||||
|
||||
let maxid = CowCell::new(0);
|
||||
|
@ -1279,6 +1352,7 @@ impl IdlArcSqlite {
|
|||
entry_cache,
|
||||
idl_cache,
|
||||
name_cache,
|
||||
idx_exists_cache,
|
||||
op_ts_max,
|
||||
allids,
|
||||
maxid,
|
||||
|
@ -1298,6 +1372,7 @@ impl IdlArcSqlite {
|
|||
let db_read = self.db.read()?;
|
||||
let idl_cache_read = self.idl_cache.read();
|
||||
let name_cache_read = self.name_cache.read();
|
||||
let idx_exists_cache_read = self.idx_exists_cache.read();
|
||||
let allids_read = self.allids.read();
|
||||
|
||||
Ok(IdlArcSqliteReadTransaction {
|
||||
|
@ -1305,6 +1380,7 @@ impl IdlArcSqlite {
|
|||
entry_cache: entry_cache_read,
|
||||
idl_cache: idl_cache_read,
|
||||
name_cache: name_cache_read,
|
||||
idx_exists_cache: idx_exists_cache_read,
|
||||
allids: allids_read,
|
||||
})
|
||||
}
|
||||
|
@ -1315,6 +1391,7 @@ impl IdlArcSqlite {
|
|||
let db_write = self.db.write()?;
|
||||
let idl_cache_write = self.idl_cache.write();
|
||||
let name_cache_write = self.name_cache.write();
|
||||
let idx_exists_cache_write = self.idx_exists_cache.write();
|
||||
let op_ts_max_write = self.op_ts_max.write();
|
||||
let allids_write = self.allids.write();
|
||||
let maxid_write = self.maxid.write();
|
||||
|
@ -1325,6 +1402,7 @@ impl IdlArcSqlite {
|
|||
entry_cache: entry_cache_write,
|
||||
idl_cache: idl_cache_write,
|
||||
name_cache: name_cache_write,
|
||||
idx_exists_cache: idx_exists_cache_write,
|
||||
op_ts_max: op_ts_max_write,
|
||||
allids: allids_write,
|
||||
maxid: maxid_write,
|
||||
|
|
|
@ -205,12 +205,15 @@ pub(crate) trait IdlSqliteTransaction {
|
|||
let mut stmt = self
|
||||
.get_conn()?
|
||||
.prepare(&format!(
|
||||
"SELECT COUNT(name) from {}.sqlite_master where name = :tname",
|
||||
"SELECT rowid from {}.sqlite_master where name = :tname LIMIT 1",
|
||||
self.get_db_name()
|
||||
))
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
let i: Option<i64> = stmt
|
||||
.query_row(&[(":tname", tname)], |row| row.get(0))
|
||||
// If the row doesn't exist, we don't mind.
|
||||
.optional()
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
match i {
|
||||
|
|
|
@ -155,3 +155,9 @@ impl Ord for (dyn IdlCacheKeyToRef + '_) {
|
|||
self.keyref().cmp(&other.keyref())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
pub struct IdxNameKey {
|
||||
pub a: Attribute,
|
||||
pub i: IndexType,
|
||||
}
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
//! Constant Entries for the IDM
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::constants::groups::idm_builtin_admin_groups;
|
||||
use crate::constants::uuids::*;
|
||||
use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew};
|
||||
use crate::idm::account::Account;
|
||||
use crate::value::PartialValue;
|
||||
use crate::value::Value;
|
||||
use crate::valueset::{ValueSet, ValueSetIutf8};
|
||||
pub use kanidm_proto::attribute::Attribute;
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use kanidm_proto::scim_v1::JsonValue;
|
||||
use kanidm_proto::v1::AccountType;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
//TODO: This would do well in the proto lib
|
||||
// together with all the other definitions.
|
||||
|
@ -202,158 +194,9 @@ impl EntryClass {
|
|||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "idm_admin",
|
||||
uuid: UUID_IDM_ADMIN,
|
||||
description: "Builtin IDM Admin account.",
|
||||
displayname: "IDM Administrator",
|
||||
};
|
||||
|
||||
pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::SystemInfo.to_value()),
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_SYSTEM_INFO)),
|
||||
(
|
||||
Attribute::Description,
|
||||
Value::new_utf8s("System (local) info and metadata object.")
|
||||
),
|
||||
(Attribute::Version, Value::Uint32(20))
|
||||
);
|
||||
|
||||
pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::DomainInfo.to_value()),
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyObject.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()),
|
||||
(Attribute::Name, Value::new_iname("domain_local")),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_DOMAIN_INFO)),
|
||||
(
|
||||
Attribute::Description,
|
||||
Value::new_utf8s("This local domain's info and metadata object.")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Built in accounts such as anonymous, idm_admin and admin
|
||||
pub struct BuiltinAccount {
|
||||
pub account_type: kanidm_proto::v1::AccountType,
|
||||
pub entry_managed_by: Option<uuid::Uuid>,
|
||||
pub name: &'static str,
|
||||
pub uuid: Uuid,
|
||||
pub description: &'static str,
|
||||
pub displayname: &'static str,
|
||||
}
|
||||
|
||||
impl Default for BuiltinAccount {
|
||||
fn default() -> Self {
|
||||
BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "",
|
||||
uuid: Uuid::new_v4(),
|
||||
description: "<set description>",
|
||||
displayname: "<set displayname>",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BuiltinAccount> for Account {
|
||||
fn from(value: BuiltinAccount) -> Self {
|
||||
#[allow(clippy::panic)]
|
||||
if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID {
|
||||
panic!("Builtin ACP has invalid UUID! {:?}", value);
|
||||
}
|
||||
Account {
|
||||
name: value.name.to_string(),
|
||||
uuid: value.uuid,
|
||||
displayname: value.displayname.to_string(),
|
||||
spn: format!("{}@example.com", value.name),
|
||||
mail_primary: None,
|
||||
mail: Vec::with_capacity(0),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BuiltinAccount> for EntryInitNew {
|
||||
fn from(value: BuiltinAccount) -> Self {
|
||||
let mut entry = EntryInitNew::new();
|
||||
entry.add_ava(Attribute::Name, Value::new_iname(value.name));
|
||||
#[allow(clippy::panic)]
|
||||
if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID {
|
||||
panic!("Builtin ACP has invalid UUID! {:?}", value);
|
||||
}
|
||||
entry.add_ava(Attribute::Uuid, Value::Uuid(value.uuid));
|
||||
entry.add_ava(Attribute::Description, Value::new_utf8s(value.description));
|
||||
entry.add_ava(Attribute::DisplayName, Value::new_utf8s(value.displayname));
|
||||
|
||||
if let Some(entry_manager) = value.entry_managed_by {
|
||||
entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager));
|
||||
}
|
||||
|
||||
entry.set_ava(
|
||||
Attribute::Class,
|
||||
vec![
|
||||
EntryClass::Account.to_value(),
|
||||
EntryClass::MemberOf.to_value(),
|
||||
EntryClass::Object.to_value(),
|
||||
],
|
||||
);
|
||||
match value.account_type {
|
||||
AccountType::Person => entry.add_ava(Attribute::Class, EntryClass::Person.to_value()),
|
||||
AccountType::ServiceAccount => {
|
||||
entry.add_ava(Attribute::Class, EntryClass::ServiceAccount.to_value())
|
||||
}
|
||||
}
|
||||
entry
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "admin",
|
||||
uuid: UUID_ADMIN,
|
||||
description: "Builtin System Admin account.",
|
||||
displayname: "System Administrator",
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
name: "anonymous",
|
||||
uuid: UUID_ANONYMOUS,
|
||||
description: "Anonymous access account.",
|
||||
displayname: "Anonymous",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn builtin_accounts() -> Vec<&'static BuiltinAccount> {
|
||||
vec![
|
||||
&BUILTIN_ACCOUNT_ADMIN,
|
||||
&BUILTIN_ACCOUNT_IDM_ADMIN,
|
||||
&BUILTIN_ACCOUNT_ANONYMOUS_DL6,
|
||||
]
|
||||
}
|
||||
|
||||
// ============ TEST DATA ============
|
||||
#[cfg(test)]
|
||||
pub const UUID_TESTPERSON_1: Uuid = ::uuid::uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
|
||||
|
||||
#[cfg(test)]
|
||||
pub const UUID_TESTPERSON_2: Uuid = ::uuid::uuid!("538faac7-4d29-473b-a59d-23023ac19955");
|
||||
use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew};
|
||||
|
||||
#[cfg(test)]
|
||||
lazy_static! {
|
||||
|
@ -363,7 +206,10 @@ lazy_static! {
|
|||
(Attribute::Class, EntryClass::Person.to_value()),
|
||||
(Attribute::Name, Value::new_iname("testperson1")),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Test Person 1")),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_TESTPERSON_1))
|
||||
(
|
||||
Attribute::Uuid,
|
||||
Value::Uuid(super::uuids::UUID_TESTPERSON_1)
|
||||
)
|
||||
);
|
||||
pub static ref E_TESTPERSON_2: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
|
@ -371,28 +217,9 @@ lazy_static! {
|
|||
(Attribute::Class, EntryClass::Person.to_value()),
|
||||
(Attribute::Name, Value::new_iname("testperson2")),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Test Person 2")),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_TESTPERSON_2))
|
||||
(
|
||||
Attribute::Uuid,
|
||||
Value::Uuid(super::uuids::UUID_TESTPERSON_2)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// ⚠️ DOMAIN LEVEL 1 ENTRIES ⚠️
|
||||
// Future entries need to be added via migrations.
|
||||
//
|
||||
// DO NOT MODIFY THIS DEFINITION
|
||||
|
||||
/// Build a list of internal admin entries
|
||||
pub fn idm_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
let mut res: Vec<EntryInitNew> = vec![
|
||||
BUILTIN_ACCOUNT_ADMIN.clone().into(),
|
||||
BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(),
|
||||
];
|
||||
for group in idm_builtin_admin_groups() {
|
||||
let g: EntryInitNew = group.clone().try_into()?;
|
||||
res.push(g);
|
||||
}
|
||||
|
||||
// We need to push anonymous *after* groups due to entry-managed-by
|
||||
res.push(BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into());
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
|
|
@ -1,20 +1,10 @@
|
|||
// Re-export as needed
|
||||
|
||||
pub mod acp;
|
||||
pub mod entries;
|
||||
pub mod groups;
|
||||
mod key_providers;
|
||||
pub mod schema;
|
||||
pub mod system_config;
|
||||
pub mod uuids;
|
||||
pub mod values;
|
||||
|
||||
pub use self::acp::*;
|
||||
pub use self::entries::*;
|
||||
pub use self::groups::*;
|
||||
pub use self::key_providers::*;
|
||||
pub use self::schema::*;
|
||||
pub use self::system_config::*;
|
||||
pub use self::uuids::*;
|
||||
pub use self::values::*;
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@ use uuid::{uuid, Uuid};
|
|||
pub const STR_UUID_ADMIN: &str = "00000000-0000-0000-0000-000000000000";
|
||||
pub const UUID_ADMIN: Uuid = uuid!("00000000-0000-0000-0000-000000000000");
|
||||
pub const UUID_IDM_ADMINS: Uuid = uuid!("00000000-0000-0000-0000-000000000001");
|
||||
pub const NAME_IDM_ADMINS: &str = "idm_admins";
|
||||
pub const UUID_IDM_PEOPLE_PII_READ: Uuid = uuid!("00000000-0000-0000-0000-000000000002");
|
||||
pub const NAME_IDM_PEOPLE_PII_READ: &str = "idm_people_pii_read";
|
||||
pub const UUID_IDM_PEOPLE_WRITE_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000003");
|
||||
pub const UUID_IDM_GROUP_WRITE_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000004");
|
||||
pub const UUID_IDM_ACCOUNT_READ_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000005");
|
||||
|
@ -26,6 +28,8 @@ pub const UUID_IDM_ADMIN: Uuid = uuid!("00000000-0000-0000-0000-000000000018");
|
|||
|
||||
pub const STR_UUID_SYSTEM_ADMINS: &str = "00000000-0000-0000-0000-000000000019";
|
||||
pub const UUID_SYSTEM_ADMINS: Uuid = uuid!("00000000-0000-0000-0000-000000000019");
|
||||
pub const NAME_SYSTEM_ADMINS: &str = "system_admins";
|
||||
|
||||
pub const UUID_DOMAIN_ADMINS: Uuid = uuid!("00000000-0000-0000-0000-000000000020");
|
||||
pub const UUID_IDM_ACCOUNT_UNIX_EXTEND_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000021");
|
||||
pub const UUID_IDM_GROUP_UNIX_EXTEND_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000022");
|
||||
|
@ -50,6 +54,7 @@ pub const UUID_IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV: Uuid =
|
|||
pub const UUID_IDM_ALL_PERSONS: Uuid = uuid!("00000000-0000-0000-0000-000000000035");
|
||||
pub const STR_UUID_IDM_ALL_ACCOUNTS: &str = "00000000-0000-0000-0000-000000000036";
|
||||
pub const UUID_IDM_ALL_ACCOUNTS: Uuid = uuid!("00000000-0000-0000-0000-000000000036");
|
||||
pub const NAME_IDM_ALL_ACCOUNTS: &str = "idm_all_accounts";
|
||||
|
||||
pub const UUID_IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV: Uuid =
|
||||
uuid!("00000000-0000-0000-0000-000000000037");
|
||||
|
@ -452,3 +457,9 @@ pub const UUID_DOES_NOT_EXIST: Uuid = uuid!("00000000-0000-0000-0000-fffffffffff
|
|||
pub const UUID_ANONYMOUS: Uuid = uuid!("00000000-0000-0000-0000-ffffffffffff");
|
||||
|
||||
pub const DYNAMIC_RANGE_MINIMUM_UUID: Uuid = uuid!("00000000-0000-0000-0001-000000000000");
|
||||
|
||||
// ======= test data ======
|
||||
#[cfg(test)]
|
||||
pub const UUID_TESTPERSON_1: Uuid = uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
|
||||
#[cfg(test)]
|
||||
pub const UUID_TESTPERSON_2: Uuid = uuid!("538faac7-4d29-473b-a59d-23023ac19955");
|
||||
|
|
|
@ -636,23 +636,6 @@ impl ModifyEvent {
|
|||
}
|
||||
}
|
||||
|
||||
/// ⚠️ - Bypass the schema state machine and force the filter to be considered valid.
|
||||
/// This is a TEST ONLY method and will never be exposed in production.
|
||||
#[cfg(test)]
|
||||
pub fn new_impersonate_entry_ser(
|
||||
e: BuiltinAccount,
|
||||
filter: Filter<FilterInvalid>,
|
||||
modlist: ModifyList<ModifyInvalid>,
|
||||
) -> Self {
|
||||
let ei: EntryInitNew = e.into();
|
||||
ModifyEvent {
|
||||
ident: Identity::from_impersonate_entry_readwrite(Arc::new(ei.into_sealed_committed())),
|
||||
filter: filter.clone().into_valid(),
|
||||
filter_orig: filter.into_valid(),
|
||||
modlist: modlist.into_valid(),
|
||||
}
|
||||
}
|
||||
|
||||
/// ⚠️ - Bypass the schema state machine and force the filter to be considered valid.
|
||||
/// This is a TEST ONLY method and will never be exposed in production.
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1041,18 +1041,10 @@ impl IdmServerProxyReadTransaction<'_> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::idm::account::Account;
|
||||
use crate::idm::accountpolicy::ResolvedAccountPolicy;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::internal::UiHint;
|
||||
|
||||
#[test]
|
||||
fn test_idm_account_from_anonymous() {
|
||||
let account: Account = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||
debug!("{:?}", account);
|
||||
// I think that's it? we may want to check anonymous mech ...
|
||||
}
|
||||
|
||||
#[idm_test]
|
||||
async fn test_idm_account_ui_hints(idms: &IdmServer, _idms_delayed: &mut IdmServerDelayed) {
|
||||
let ct = duration_from_epoch_now();
|
||||
|
|
|
@ -1716,6 +1716,7 @@ mod tests {
|
|||
};
|
||||
use crate::idm::delayed::DelayedAction;
|
||||
use crate::idm::AuthState;
|
||||
use crate::migration_data::{BUILTIN_ACCOUNT_ANONYMOUS, BUILTIN_ACCOUNT_TEST_PERSON};
|
||||
use crate::prelude::*;
|
||||
use crate::server::keys::KeyObjectInternal;
|
||||
use crate::utils::readable_password_from_random;
|
||||
|
@ -1742,7 +1743,7 @@ mod tests {
|
|||
|
||||
let webauthn = create_webauthn();
|
||||
|
||||
let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||
let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS.clone().into();
|
||||
|
||||
let asd = AuthSessionData {
|
||||
account: anon_account,
|
||||
|
@ -1819,7 +1820,7 @@ mod tests {
|
|||
fn start_session_simple_password_mech(privileged: bool) -> UserAuthToken {
|
||||
let webauthn = create_webauthn();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
// manually load in a cred
|
||||
let p = CryptoPolicy::minimum();
|
||||
let cred = Credential::new_password_only(&p, "test_password").unwrap();
|
||||
|
@ -1920,7 +1921,7 @@ mod tests {
|
|||
sketching::test_init();
|
||||
let webauthn = create_webauthn();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
// manually load in a cred
|
||||
let p = CryptoPolicy::minimum();
|
||||
let cred = Credential::new_password_only(&p, "list@no3IBTyqHu$bad").unwrap();
|
||||
|
@ -2087,7 +2088,7 @@ mod tests {
|
|||
sketching::test_init();
|
||||
let webauthn = create_webauthn();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
// Setup a fake time stamp for consistency.
|
||||
let ts = Duration::from_secs(12345);
|
||||
|
@ -2264,7 +2265,7 @@ mod tests {
|
|||
sketching::test_init();
|
||||
let webauthn = create_webauthn();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
// Setup a fake time stamp for consistency.
|
||||
let ts = Duration::from_secs(12345);
|
||||
|
@ -2440,7 +2441,7 @@ mod tests {
|
|||
let (audit_tx, mut audit_rx) = unbounded();
|
||||
let ts = duration_from_epoch_now();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
let (webauthn, mut wa, wan_cred) = setup_webauthn_passkey(account.name.as_str());
|
||||
|
||||
|
@ -2594,7 +2595,7 @@ mod tests {
|
|||
let (audit_tx, mut audit_rx) = unbounded();
|
||||
let ts = duration_from_epoch_now();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
let (webauthn, mut wa, wan_cred) = setup_webauthn_securitykey(account.name.as_str());
|
||||
let pw_good = "test_password";
|
||||
|
@ -2787,7 +2788,7 @@ mod tests {
|
|||
let (audit_tx, mut audit_rx) = unbounded();
|
||||
let ts = duration_from_epoch_now();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
let (webauthn, mut wa, wan_cred) = setup_webauthn_securitykey(account.name.as_str());
|
||||
|
||||
|
@ -3053,7 +3054,7 @@ mod tests {
|
|||
sketching::test_init();
|
||||
let webauthn = create_webauthn();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
// Setup a fake time stamp for consistency.
|
||||
let ts = Duration::from_secs(12345);
|
||||
|
@ -3262,7 +3263,7 @@ mod tests {
|
|||
sketching::test_init();
|
||||
let webauthn = create_webauthn();
|
||||
// create the ent
|
||||
let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into();
|
||||
let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into();
|
||||
|
||||
// Setup a fake time stamp for consistency.
|
||||
let ts = Duration::from_secs(12345);
|
||||
|
|
|
@ -1989,7 +1989,7 @@ mod tests {
|
|||
let me = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(
|
||||
Attribute::Name,
|
||||
PartialValue::new_iname(BUILTIN_GROUP_PEOPLE_PII_READ.name)
|
||||
PartialValue::new_iname("idm_people_pii_read")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member,
|
||||
|
|
|
@ -143,8 +143,9 @@ impl IdmServer {
|
|||
pub async fn new(
|
||||
qs: QueryServer,
|
||||
origin: &str,
|
||||
is_integration_test: bool,
|
||||
) -> Result<(IdmServer, IdmServerDelayed, IdmServerAudit), OperationError> {
|
||||
let crypto_policy = if cfg!(test) {
|
||||
let crypto_policy = if cfg!(test) || is_integration_test {
|
||||
CryptoPolicy::danger_test_minimum()
|
||||
} else {
|
||||
// This is calculated back from:
|
||||
|
|
|
@ -50,6 +50,12 @@ pub mod credential;
|
|||
pub mod entry;
|
||||
pub mod event;
|
||||
pub mod filter;
|
||||
|
||||
// If this module is ever made public outside of this crate, firstyear will be extremely sad.
|
||||
// This is *purely migration data*. Don't even think about using it in test cases for anything
|
||||
// else.
|
||||
pub(crate) mod migration_data;
|
||||
|
||||
pub mod modify;
|
||||
pub mod time;
|
||||
pub(crate) mod utils;
|
||||
|
|
35
server/lib/src/migration_data/dl10/accounts.rs
Normal file
35
server/lib/src/migration_data/dl10/accounts.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
//! Constant Entries for the IDM
|
||||
use crate::constants::uuids::*;
|
||||
use crate::migration_data::types::BuiltinAccount;
|
||||
use kanidm_proto::v1::AccountType;
|
||||
|
||||
lazy_static! {
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "idm_admin",
|
||||
uuid: UUID_IDM_ADMIN,
|
||||
description: "Builtin IDM Admin account.",
|
||||
displayname: "IDM Administrator",
|
||||
};
|
||||
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "admin",
|
||||
uuid: UUID_ADMIN,
|
||||
description: "Builtin System Admin account.",
|
||||
displayname: "System Administrator",
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
name: "anonymous",
|
||||
uuid: UUID_ANONYMOUS,
|
||||
description: "Anonymous access account.",
|
||||
displayname: "Anonymous",
|
||||
};
|
||||
}
|
408
server/lib/src/migration_data/dl10/groups.rs
Normal file
408
server/lib/src/migration_data/dl10/groups.rs
Normal file
|
@ -0,0 +1,408 @@
|
|||
use crate::entry::EntryInitNew;
|
||||
use crate::prelude::*;
|
||||
use crate::value::CredentialType;
|
||||
|
||||
use kanidm_proto::internal::{Filter, OperationError, UiHint};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
/// Built-in group definitions
|
||||
pub struct BuiltinGroup {
|
||||
pub name: &'static str,
|
||||
pub description: &'static str,
|
||||
pub uuid: uuid::Uuid,
|
||||
pub members: Vec<uuid::Uuid>,
|
||||
pub entry_managed_by: Option<uuid::Uuid>,
|
||||
pub dyngroup: bool,
|
||||
pub dyngroup_filter: Option<Filter>,
|
||||
pub extra_attributes: Vec<(Attribute, Value)>,
|
||||
}
|
||||
|
||||
impl TryFrom<BuiltinGroup> for EntryInitNew {
|
||||
type Error = OperationError;
|
||||
|
||||
fn try_from(val: BuiltinGroup) -> Result<Self, OperationError> {
|
||||
let mut entry = EntryInitNew::new();
|
||||
|
||||
if val.uuid >= DYNAMIC_RANGE_MINIMUM_UUID {
|
||||
error!("Builtin ACP has invalid UUID! {:?}", val);
|
||||
return Err(OperationError::InvalidUuid);
|
||||
}
|
||||
|
||||
entry.add_ava(Attribute::Name, Value::new_iname(val.name));
|
||||
entry.add_ava(Attribute::Description, Value::new_utf8s(val.description));
|
||||
// classes for groups
|
||||
entry.set_ava(
|
||||
Attribute::Class,
|
||||
vec![EntryClass::Group.into(), EntryClass::Object.into()],
|
||||
);
|
||||
if val.dyngroup {
|
||||
if !val.members.is_empty() {
|
||||
return Err(OperationError::InvalidSchemaState(format!(
|
||||
"Builtin dyngroup {} has members specified, this is not allowed",
|
||||
val.name
|
||||
)));
|
||||
}
|
||||
entry.add_ava(Attribute::Class, EntryClass::DynGroup.to_value());
|
||||
match val.dyngroup_filter {
|
||||
Some(filter) => entry.add_ava(Attribute::DynGroupFilter, Value::JsonFilt(filter)),
|
||||
None => {
|
||||
error!(
|
||||
"No filter specified for dyngroup '{}' this is going to break things!",
|
||||
val.name
|
||||
);
|
||||
return Err(OperationError::FilterGeneration);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(entry_manager) = val.entry_managed_by {
|
||||
entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager));
|
||||
}
|
||||
|
||||
entry.add_ava(Attribute::Uuid, Value::Uuid(val.uuid));
|
||||
entry.set_ava(
|
||||
Attribute::Member,
|
||||
val.members
|
||||
.into_iter()
|
||||
.map(Value::Refer)
|
||||
.collect::<Vec<Value>>(),
|
||||
);
|
||||
// add any extra attributes
|
||||
val.extra_attributes
|
||||
.into_iter()
|
||||
.for_each(|(attr, val)| entry.add_ava(attr, val));
|
||||
// all done!
|
||||
Ok(entry)
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// There are our built in "roles". They encapsulate some higher level collections
|
||||
// of roles. The intent is to allow a pretty generic and correct by default set
|
||||
// of these use cases.
|
||||
pub static ref BUILTIN_GROUP_SYSTEM_ADMINS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: NAME_SYSTEM_ADMINS,
|
||||
description: "Builtin System Administrators Group.",
|
||||
uuid: UUID_SYSTEM_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_ADMIN],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_IDM_ADMINS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: NAME_IDM_ADMINS,
|
||||
description: "Builtin IDM Administrators Group.",
|
||||
uuid: UUID_IDM_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMIN],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_SERVICE_DESK: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_service_desk",
|
||||
description: "Builtin Service Desk Group.",
|
||||
uuid: UUID_IDM_SERVICE_DESK,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// These are the "finer" roles. They encapsulate different concepts in the system.
|
||||
// The next section is the "system style" roles. These adjust the operation of
|
||||
// kanidm and relate to it's internals and how it functions.
|
||||
pub static ref BUILTIN_GROUP_RECYCLE_BIN_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_recycle_bin_admins",
|
||||
description: "Builtin Recycle Bin Administrators Group.",
|
||||
uuid: UUID_IDM_RECYCLE_BIN_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting local domain administration rights and trust administration rights
|
||||
pub static ref BUILTIN_GROUP_DOMAIN_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "domain_admins",
|
||||
description: "Builtin IDM Group for granting local domain administration rights and trust administration rights.",
|
||||
uuid: UUID_DOMAIN_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_SCHEMA_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_schema_admins",
|
||||
description: "Builtin Schema Administration Group.",
|
||||
uuid: UUID_IDM_SCHEMA_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_ACCESS_CONTROL_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_access_control_admins",
|
||||
description: "Builtin Access Control Administration Group.",
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
uuid: UUID_IDM_ACCESS_CONTROL_ADMINS,
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// These are the IDM roles. They concern application integration, user permissions
|
||||
// and credential security management.
|
||||
|
||||
/// Builtin IDM Group for managing persons and their account details
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_admins",
|
||||
description: "Builtin People Administration Group.",
|
||||
uuid: UUID_IDM_PEOPLE_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_ON_BOARDING: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_on_boarding",
|
||||
description: "Builtin People On Boarding Group.",
|
||||
uuid: UUID_IDM_PEOPLE_ON_BOARDING,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting elevated people (personal data) read permissions.
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_PII_READ: BuiltinGroup = BuiltinGroup {
|
||||
name: NAME_IDM_PEOPLE_PII_READ,
|
||||
description: "Builtin IDM Group for granting elevated people (personal data) read permissions.",
|
||||
uuid: UUID_IDM_PEOPLE_PII_READ,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting people the ability to write to their own name attributes.
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_self_name_write",
|
||||
description: "Builtin IDM Group denoting users that can write to their own name attributes.",
|
||||
uuid: UUID_IDM_PEOPLE_SELF_NAME_WRITE,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![
|
||||
UUID_IDM_ALL_PERSONS
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_service_account_admins",
|
||||
description: "Builtin Service Account Administration Group.",
|
||||
uuid: UUID_IDM_SERVICE_ACCOUNT_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain.
|
||||
pub static ref BUILTIN_GROUP_OAUTH2_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_oauth2_admins",
|
||||
description: "Builtin Oauth2 Integration Administration Group.",
|
||||
uuid: UUID_IDM_OAUTH2_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_RADIUS_SERVICE_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_radius_service_admins",
|
||||
description: "Builtin Radius Administration Group.",
|
||||
uuid: UUID_IDM_RADIUS_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for RADIUS server access delegation.
|
||||
pub static ref BUILTIN_IDM_RADIUS_SERVERS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_radius_servers",
|
||||
description: "Builtin IDM Group for RADIUS server access delegation.",
|
||||
uuid: UUID_IDM_RADIUS_SERVERS,
|
||||
entry_managed_by: Some(UUID_IDM_RADIUS_ADMINS),
|
||||
members: vec![
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_mail_service_admins",
|
||||
description: "Builtin Mail Server Administration Group.",
|
||||
uuid: UUID_IDM_MAIL_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for MAIL server Access delegation.
|
||||
pub static ref BUILTIN_IDM_MAIL_SERVERS_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_mail_servers",
|
||||
description: "Builtin IDM Group for MAIL server access delegation.",
|
||||
uuid: UUID_IDM_MAIL_SERVERS,
|
||||
entry_managed_by: Some(UUID_IDM_MAIL_ADMINS),
|
||||
members: vec![
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_account_policy_admins",
|
||||
description: "Builtin Account Policy Administration Group.",
|
||||
uuid: UUID_IDM_ACCOUNT_POLICY_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for managing posix/unix attributes on groups and users.
|
||||
pub static ref BUILTIN_GROUP_UNIX_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_unix_admins",
|
||||
description: "Builtin Unix Administration Group.",
|
||||
uuid: UUID_IDM_UNIX_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for managing client authentication certificates.
|
||||
pub static ref BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_client_certificate_admins",
|
||||
description: "Builtin Client Certificate Administration Group.",
|
||||
uuid: UUID_IDM_CLIENT_CERTIFICATE_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting elevated group write and lifecycle permissions.
|
||||
pub static ref IDM_GROUP_ADMINS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_group_admins",
|
||||
description: "Builtin IDM Group for granting elevated group write and lifecycle permissions.",
|
||||
uuid: UUID_IDM_GROUP_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Self-write of mail
|
||||
pub static ref IDM_PEOPLE_SELF_MAIL_WRITE_DL7: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_self_mail_write",
|
||||
description: "Builtin IDM Group for people accounts to update their own mail.",
|
||||
uuid: UUID_IDM_PEOPLE_SELF_MAIL_WRITE,
|
||||
members: Vec::with_capacity(0),
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
// at some point vs code just gives up on syntax highlighting inside lazy_static...
|
||||
lazy_static! {
|
||||
pub static ref IDM_ALL_PERSONS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_all_persons",
|
||||
description: "Builtin IDM dynamic group containing all persons.",
|
||||
uuid: UUID_IDM_ALL_PERSONS,
|
||||
members: Vec::with_capacity(0),
|
||||
dyngroup: true,
|
||||
dyngroup_filter: Some(
|
||||
Filter::And(vec![
|
||||
Filter::Eq(Attribute::Class.to_string(), EntryClass::Person.to_string()),
|
||||
Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()),
|
||||
])
|
||||
),
|
||||
extra_attributes: vec![
|
||||
// Enable account policy by default
|
||||
(Attribute::Class, EntryClass::AccountPolicy.to_value()),
|
||||
// Enforce this is a system protected object
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
// MFA By Default
|
||||
(Attribute::CredentialTypeMinimum, CredentialType::Mfa.into()),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref IDM_ALL_ACCOUNTS: BuiltinGroup = BuiltinGroup {
|
||||
name: NAME_IDM_ALL_ACCOUNTS,
|
||||
description: "Builtin IDM dynamic group containing all entries that can authenticate.",
|
||||
uuid: UUID_IDM_ALL_ACCOUNTS,
|
||||
members: Vec::with_capacity(0),
|
||||
dyngroup: true,
|
||||
dyngroup_filter: Some(
|
||||
Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()),
|
||||
),
|
||||
extra_attributes: vec![
|
||||
// Enable account policy by default
|
||||
(Attribute::Class, EntryClass::AccountPolicy.to_value()),
|
||||
// Enforce this is a system protected object
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
pub static ref IDM_UI_ENABLE_EXPERIMENTAL_FEATURES: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_ui_enable_experimental_features",
|
||||
description: "Members of this group will have access to experimental web UI features.",
|
||||
uuid: UUID_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
extra_attributes: vec![
|
||||
(Attribute::GrantUiHint, Value::UiHint(UiHint::ExperimentalFeatures))
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Members of this group will have access to read the mail attribute of all persons and service accounts.
|
||||
pub static ref IDM_ACCOUNT_MAIL_READ: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_account_mail_read",
|
||||
description: "Members of this group will have access to read the mail attribute of all persons and service accounts.",
|
||||
entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS),
|
||||
uuid: UUID_IDM_ACCOUNT_MAIL_READ,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// This must be the last group to init to include the UUID of the other high priv groups.
|
||||
pub static ref IDM_HIGH_PRIVILEGE_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_high_privilege",
|
||||
uuid: UUID_IDM_HIGH_PRIVILEGE,
|
||||
entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS),
|
||||
description: "Builtin IDM provided groups with high levels of access that should be audited and limited in modification.",
|
||||
members: vec![
|
||||
UUID_SYSTEM_ADMINS,
|
||||
UUID_IDM_ADMINS,
|
||||
UUID_DOMAIN_ADMINS,
|
||||
UUID_IDM_SERVICE_DESK,
|
||||
UUID_IDM_RECYCLE_BIN_ADMINS,
|
||||
UUID_IDM_SCHEMA_ADMINS,
|
||||
UUID_IDM_ACCESS_CONTROL_ADMINS,
|
||||
UUID_IDM_OAUTH2_ADMINS,
|
||||
UUID_IDM_RADIUS_ADMINS,
|
||||
UUID_IDM_ACCOUNT_POLICY_ADMINS,
|
||||
UUID_IDM_RADIUS_SERVERS,
|
||||
UUID_IDM_GROUP_ADMINS,
|
||||
UUID_IDM_UNIX_ADMINS,
|
||||
UUID_IDM_PEOPLE_PII_READ,
|
||||
UUID_IDM_PEOPLE_ADMINS,
|
||||
UUID_IDM_PEOPLE_ON_BOARDING,
|
||||
UUID_IDM_SERVICE_ACCOUNT_ADMINS,
|
||||
UUID_IDM_CLIENT_CERTIFICATE_ADMINS,
|
||||
UUID_IDM_APPLICATION_ADMINS,
|
||||
UUID_IDM_MAIL_ADMINS,
|
||||
UUID_IDM_HIGH_PRIVILEGE,
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_APPLICATION_ADMINS_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_application_admins",
|
||||
uuid: UUID_IDM_APPLICATION_ADMINS,
|
||||
description: "Builtin Application Administration Group.",
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
268
server/lib/src/migration_data/dl10/mod.rs
Normal file
268
server/lib/src/migration_data/dl10/mod.rs
Normal file
|
@ -0,0 +1,268 @@
|
|||
mod access;
|
||||
pub(super) mod accounts;
|
||||
mod groups;
|
||||
mod key_providers;
|
||||
mod schema;
|
||||
mod system_config;
|
||||
|
||||
use self::access::*;
|
||||
use self::accounts::*;
|
||||
use self::groups::*;
|
||||
use self::key_providers::*;
|
||||
use self::schema::*;
|
||||
use self::system_config::*;
|
||||
|
||||
use crate::prelude::EntryInitNew;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
|
||||
pub fn phase_1_schema_attrs() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(),
|
||||
SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(),
|
||||
SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(),
|
||||
SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_NAME.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_SSID.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_UUID.clone().into(),
|
||||
SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(),
|
||||
SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(),
|
||||
SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(),
|
||||
SCHEMA_ATTR_GIDNUMBER.clone().into(),
|
||||
SCHEMA_ATTR_GRANT_UI_HINT.clone().into(),
|
||||
SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_LOGINSHELL.clone().into(),
|
||||
SCHEMA_ATTR_NAME_HISTORY.clone().into(),
|
||||
SCHEMA_ATTR_NSUNIQUEID.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
|
||||
.clone()
|
||||
.into(),
|
||||
SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(),
|
||||
SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_RADIUS_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_COOKIE.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_UNIX_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_DENIED_NAME.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(),
|
||||
SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4
|
||||
.clone()
|
||||
.into(),
|
||||
// DL5
|
||||
// DL6
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(),
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(),
|
||||
// DL7
|
||||
SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(),
|
||||
SCHEMA_ATTR_REFERS_DL7.clone().into(),
|
||||
SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(),
|
||||
SCHEMA_ATTR_MAIL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_LEGALNAME_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(),
|
||||
SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(),
|
||||
SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(),
|
||||
// DL9
|
||||
SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(),
|
||||
// DL10
|
||||
SCHEMA_ATTR_DENIED_NAME_DL10.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_2_schema_classes() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
SCHEMA_CLASS_DYNGROUP.clone().into(),
|
||||
SCHEMA_CLASS_ORGPERSON.clone().into(),
|
||||
SCHEMA_CLASS_POSIXACCOUNT.clone().into(),
|
||||
SCHEMA_CLASS_POSIXGROUP.clone().into(),
|
||||
SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(),
|
||||
// DL5
|
||||
SCHEMA_CLASS_ACCOUNT_DL5.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(),
|
||||
// DL6
|
||||
SCHEMA_CLASS_GROUP_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(),
|
||||
// DL7
|
||||
SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(),
|
||||
SCHEMA_CLASS_APPLICATION_DL8.clone().into(),
|
||||
SCHEMA_CLASS_PERSON_DL8.clone().into(),
|
||||
// DL9
|
||||
SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(),
|
||||
// DL10
|
||||
SCHEMA_CLASS_DOMAIN_INFO_DL10.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_3_key_provider() -> Vec<EntryInitNew> {
|
||||
vec![E_KEY_PROVIDER_INTERNAL_DL6.clone()]
|
||||
}
|
||||
|
||||
pub fn phase_4_system_entries() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
E_SYSTEM_INFO_V1.clone(),
|
||||
E_DOMAIN_INFO_DL6.clone(),
|
||||
E_SYSTEM_CONFIG_V1.clone(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_5_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
Ok(vec![
|
||||
BUILTIN_ACCOUNT_ADMIN.clone().into(),
|
||||
BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(),
|
||||
BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?,
|
||||
BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?,
|
||||
// We need to push anonymous *after* groups due to entry-managed-by
|
||||
BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn phase_6_builtin_non_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
Ok(vec![
|
||||
BUILTIN_GROUP_DOMAIN_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_SCHEMA_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_ACCESS_CONTROL_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_UNIX_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_RECYCLE_BIN_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_SERVICE_DESK.clone().try_into()?,
|
||||
BUILTIN_GROUP_OAUTH2_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_RADIUS_SERVICE_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_PII_READ.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_ON_BOARDING.clone().try_into()?,
|
||||
BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8.clone().try_into()?,
|
||||
IDM_GROUP_ADMINS_V1.clone().try_into()?,
|
||||
IDM_ALL_PERSONS.clone().try_into()?,
|
||||
IDM_ALL_ACCOUNTS.clone().try_into()?,
|
||||
BUILTIN_IDM_RADIUS_SERVERS_V1.clone().try_into()?,
|
||||
BUILTIN_IDM_MAIL_SERVERS_DL8.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7
|
||||
.clone()
|
||||
.try_into()?,
|
||||
IDM_PEOPLE_SELF_MAIL_WRITE_DL7.clone().try_into()?,
|
||||
BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7
|
||||
.clone()
|
||||
.try_into()?,
|
||||
BUILTIN_GROUP_APPLICATION_ADMINS_DL8.clone().try_into()?,
|
||||
// Write deps on read.clone().try_into()?, so write must be added first.
|
||||
// All members must exist before we write HP
|
||||
IDM_HIGH_PRIVILEGE_DL8.clone().try_into()?,
|
||||
// other things
|
||||
IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone().try_into()?,
|
||||
IDM_ACCOUNT_MAIL_READ.clone().try_into()?,
|
||||
])
|
||||
}
|
||||
|
||||
pub fn phase_7_builtin_access_control_profiles() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
// Built in access controls.
|
||||
IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(),
|
||||
IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(),
|
||||
IDM_ACP_ACP_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SERVERS_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(),
|
||||
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(),
|
||||
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(),
|
||||
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_GROUP_READ_V1.clone().into(),
|
||||
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_DELETE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
// DL4
|
||||
// DL5
|
||||
// DL6
|
||||
IDM_ACP_PEOPLE_CREATE_DL6.clone().into(),
|
||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(),
|
||||
// DL7
|
||||
IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(),
|
||||
IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(),
|
||||
// DL8
|
||||
IDM_ACP_SELF_READ_DL8.clone().into(),
|
||||
IDM_ACP_SELF_WRITE_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(),
|
||||
IDM_ACP_MAIL_SERVERS_DL8.clone().into(),
|
||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(),
|
||||
// DL9
|
||||
IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(),
|
||||
IDM_ACP_GROUP_MANAGE_DL9.clone().into(),
|
||||
IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(),
|
||||
]
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
//! Core Constants
|
||||
//!
|
||||
//! Schema uuids start at `00000000-0000-0000-0000-ffff00000000`
|
||||
//!
|
||||
//! Schema Entries
|
||||
use crate::constants::entries::{Attribute, EntryClass};
|
||||
use crate::constants::uuids::*;
|
||||
use crate::schema::{SchemaAttribute, SchemaClass};
|
|
@ -8,6 +8,31 @@ use crate::value::Value;
|
|||
// This is separated because the password badlist section may become very long
|
||||
|
||||
lazy_static! {
|
||||
pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::SystemInfo.to_value()),
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_SYSTEM_INFO)),
|
||||
(
|
||||
Attribute::Description,
|
||||
Value::new_utf8s("System (local) info and metadata object.")
|
||||
),
|
||||
(Attribute::Version, Value::Uint32(20))
|
||||
);
|
||||
pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::DomainInfo.to_value()),
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyObject.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()),
|
||||
(Attribute::Name, Value::new_iname("domain_local")),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_DOMAIN_INFO)),
|
||||
(
|
||||
Attribute::Description,
|
||||
Value::new_utf8s("This local domain's info and metadata object.")
|
||||
)
|
||||
);
|
||||
pub static ref E_SYSTEM_CONFIG_V1: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::SystemConfig.to_value()),
|
2637
server/lib/src/migration_data/dl8/access.rs
Normal file
2637
server/lib/src/migration_data/dl8/access.rs
Normal file
File diff suppressed because it is too large
Load diff
35
server/lib/src/migration_data/dl8/accounts.rs
Normal file
35
server/lib/src/migration_data/dl8/accounts.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
//! Constant Entries for the IDM
|
||||
use crate::constants::uuids::*;
|
||||
use crate::migration_data::types::BuiltinAccount;
|
||||
use kanidm_proto::v1::AccountType;
|
||||
|
||||
lazy_static! {
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "idm_admin",
|
||||
uuid: UUID_IDM_ADMIN,
|
||||
description: "Builtin IDM Admin account.",
|
||||
displayname: "IDM Administrator",
|
||||
};
|
||||
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "admin",
|
||||
uuid: UUID_ADMIN,
|
||||
description: "Builtin System Admin account.",
|
||||
displayname: "System Administrator",
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
name: "anonymous",
|
||||
uuid: UUID_ANONYMOUS,
|
||||
description: "Anonymous access account.",
|
||||
displayname: "Anonymous",
|
||||
};
|
||||
}
|
|
@ -106,7 +106,9 @@ lazy_static! {
|
|||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// These are the "finer" roles. They encapsulate different concepts in the system.
|
||||
// The next section is the "system style" roles. These adjust the operation of
|
||||
// kanidm and relate to it's internals and how it functions.
|
||||
|
@ -404,46 +406,3 @@ lazy_static! {
|
|||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
/// Make a list of all the non-admin BuiltinGroup's that are created by default, doing it in a standard-ish way so we can use it around the platform
|
||||
pub fn idm_builtin_non_admin_groups() -> Vec<&'static BuiltinGroup> {
|
||||
// Create any system default schema entries.
|
||||
vec![
|
||||
&BUILTIN_GROUP_DOMAIN_ADMINS,
|
||||
&BUILTIN_GROUP_SCHEMA_ADMINS,
|
||||
&BUILTIN_GROUP_ACCESS_CONTROL_ADMINS,
|
||||
&BUILTIN_GROUP_UNIX_ADMINS,
|
||||
&BUILTIN_GROUP_RECYCLE_BIN_ADMINS,
|
||||
&BUILTIN_GROUP_SERVICE_DESK,
|
||||
&BUILTIN_GROUP_OAUTH2_ADMINS,
|
||||
&BUILTIN_GROUP_RADIUS_SERVICE_ADMINS,
|
||||
&BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS,
|
||||
&BUILTIN_GROUP_PEOPLE_ADMINS,
|
||||
&BUILTIN_GROUP_PEOPLE_PII_READ,
|
||||
&BUILTIN_GROUP_PEOPLE_ON_BOARDING,
|
||||
&BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS,
|
||||
&BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8,
|
||||
&IDM_GROUP_ADMINS_V1,
|
||||
&IDM_ALL_PERSONS,
|
||||
&IDM_ALL_ACCOUNTS,
|
||||
&BUILTIN_IDM_RADIUS_SERVERS_V1,
|
||||
&BUILTIN_IDM_MAIL_SERVERS_DL8,
|
||||
&BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7,
|
||||
&IDM_PEOPLE_SELF_MAIL_WRITE_DL7,
|
||||
&BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7,
|
||||
&BUILTIN_GROUP_APPLICATION_ADMINS_DL8,
|
||||
// Write deps on read, so write must be added first.
|
||||
// All members must exist before we write HP
|
||||
&IDM_HIGH_PRIVILEGE_DL8,
|
||||
// other things
|
||||
&IDM_UI_ENABLE_EXPERIMENTAL_FEATURES,
|
||||
&IDM_ACCOUNT_MAIL_READ,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn idm_builtin_admin_groups() -> Vec<&'static BuiltinGroup> {
|
||||
vec![
|
||||
&BUILTIN_GROUP_SYSTEM_ADMINS_V1,
|
||||
&BUILTIN_GROUP_IDM_ADMINS_V1,
|
||||
]
|
||||
}
|
18
server/lib/src/migration_data/dl8/key_providers.rs
Normal file
18
server/lib/src/migration_data/dl8/key_providers.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use crate::constants::entries::{Attribute, EntryClass};
|
||||
use crate::constants::uuids::UUID_KEY_PROVIDER_INTERNAL;
|
||||
use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew};
|
||||
use crate::value::Value;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref E_KEY_PROVIDER_INTERNAL_DL6: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyProvider.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyProviderInternal.to_value()),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_KEY_PROVIDER_INTERNAL)),
|
||||
(Attribute::Name, Value::new_iname("key_provider_internal")),
|
||||
(
|
||||
Attribute::Description,
|
||||
Value::new_utf8s("The default database internal cryptographic key provider.")
|
||||
)
|
||||
);
|
||||
}
|
273
server/lib/src/migration_data/dl8/mod.rs
Normal file
273
server/lib/src/migration_data/dl8/mod.rs
Normal file
|
@ -0,0 +1,273 @@
|
|||
mod access;
|
||||
mod accounts;
|
||||
mod groups;
|
||||
mod key_providers;
|
||||
mod schema;
|
||||
mod system_config;
|
||||
|
||||
use self::access::*;
|
||||
use self::accounts::*;
|
||||
use self::groups::*;
|
||||
use self::key_providers::*;
|
||||
use self::schema::*;
|
||||
use self::system_config::*;
|
||||
|
||||
use crate::prelude::EntryInitNew;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
|
||||
pub fn phase_1_schema_attrs() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(),
|
||||
SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(),
|
||||
SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(),
|
||||
SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_NAME.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_SSID.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_UUID.clone().into(),
|
||||
SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(),
|
||||
SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(),
|
||||
SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(),
|
||||
SCHEMA_ATTR_GIDNUMBER.clone().into(),
|
||||
SCHEMA_ATTR_GRANT_UI_HINT.clone().into(),
|
||||
SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_LOGINSHELL.clone().into(),
|
||||
SCHEMA_ATTR_NAME_HISTORY.clone().into(),
|
||||
SCHEMA_ATTR_NSUNIQUEID.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
|
||||
.clone()
|
||||
.into(),
|
||||
SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(),
|
||||
SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_RADIUS_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_COOKIE.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_UNIX_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_DENIED_NAME.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(),
|
||||
SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4
|
||||
.clone()
|
||||
.into(),
|
||||
// DL5
|
||||
// DL6
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(),
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(),
|
||||
// DL7
|
||||
SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(),
|
||||
SCHEMA_ATTR_REFERS_DL7.clone().into(),
|
||||
SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(),
|
||||
SCHEMA_ATTR_MAIL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_LEGALNAME_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(),
|
||||
SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(),
|
||||
SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_2_schema_classes() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
SCHEMA_CLASS_DYNGROUP.clone().into(),
|
||||
SCHEMA_CLASS_ORGPERSON.clone().into(),
|
||||
SCHEMA_CLASS_POSIXACCOUNT.clone().into(),
|
||||
SCHEMA_CLASS_POSIXGROUP.clone().into(),
|
||||
SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(),
|
||||
// DL5
|
||||
// SCHEMA_CLASS_PERSON_DL5.clone().into(),
|
||||
SCHEMA_CLASS_ACCOUNT_DL5.clone().into(),
|
||||
// SCHEMA_CLASS_OAUTH2_RS_DL5.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(),
|
||||
// DL6
|
||||
// SCHEMA_CLASS_ACCOUNT_POLICY_DL6.clone().into(),
|
||||
// SCHEMA_CLASS_SERVICE_ACCOUNT_DL6.clone().into(),
|
||||
// SCHEMA_CLASS_SYNC_ACCOUNT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_GROUP_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(),
|
||||
// SCHEMA_CLASS_DOMAIN_INFO_DL6.clone().into(),
|
||||
// DL7
|
||||
// SCHEMA_CLASS_DOMAIN_INFO_DL7.clone().into(),
|
||||
SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(),
|
||||
SCHEMA_CLASS_APPLICATION_DL8.clone().into(),
|
||||
SCHEMA_CLASS_PERSON_DL8.clone().into(),
|
||||
SCHEMA_CLASS_DOMAIN_INFO_DL8.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_3_key_provider() -> Vec<EntryInitNew> {
|
||||
vec![E_KEY_PROVIDER_INTERNAL_DL6.clone()]
|
||||
}
|
||||
|
||||
pub fn phase_4_system_entries() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
E_SYSTEM_INFO_V1.clone(),
|
||||
E_DOMAIN_INFO_DL6.clone(),
|
||||
E_SYSTEM_CONFIG_V1.clone(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_5_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
Ok(vec![
|
||||
BUILTIN_ACCOUNT_ADMIN.clone().into(),
|
||||
BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(),
|
||||
BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?,
|
||||
BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?,
|
||||
// We need to push anonymous *after* groups due to entry-managed-by
|
||||
BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn phase_6_builtin_non_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
Ok(vec![
|
||||
BUILTIN_GROUP_DOMAIN_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_SCHEMA_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_ACCESS_CONTROL_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_UNIX_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_RECYCLE_BIN_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_SERVICE_DESK.clone().try_into()?,
|
||||
BUILTIN_GROUP_OAUTH2_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_RADIUS_SERVICE_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_PII_READ.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_ON_BOARDING.clone().try_into()?,
|
||||
BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8.clone().try_into()?,
|
||||
IDM_GROUP_ADMINS_V1.clone().try_into()?,
|
||||
IDM_ALL_PERSONS.clone().try_into()?,
|
||||
IDM_ALL_ACCOUNTS.clone().try_into()?,
|
||||
BUILTIN_IDM_RADIUS_SERVERS_V1.clone().try_into()?,
|
||||
BUILTIN_IDM_MAIL_SERVERS_DL8.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7
|
||||
.clone()
|
||||
.try_into()?,
|
||||
IDM_PEOPLE_SELF_MAIL_WRITE_DL7.clone().try_into()?,
|
||||
BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7
|
||||
.clone()
|
||||
.try_into()?,
|
||||
BUILTIN_GROUP_APPLICATION_ADMINS_DL8.clone().try_into()?,
|
||||
// Write deps on read.clone().try_into()?, so write must be added first.
|
||||
// All members must exist before we write HP
|
||||
IDM_HIGH_PRIVILEGE_DL8.clone().try_into()?,
|
||||
// other things
|
||||
IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone().try_into()?,
|
||||
IDM_ACCOUNT_MAIL_READ.clone().try_into()?,
|
||||
])
|
||||
}
|
||||
|
||||
pub fn phase_7_builtin_access_control_profiles() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
// Built in access controls.
|
||||
IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(),
|
||||
IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(),
|
||||
IDM_ACP_ACP_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SERVERS_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(),
|
||||
// IDM_ACP_SELF_READ_V1.clone(),
|
||||
// IDM_ACP_SELF_WRITE_V1.clone(),
|
||||
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(),
|
||||
// IDM_ACP_SELF_NAME_WRITE_V1.clone(),
|
||||
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(),
|
||||
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_GROUP_READ_V1.clone().into(),
|
||||
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_DELETE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
// DL4
|
||||
// DL5
|
||||
// IDM_ACP_OAUTH2_MANAGE_DL5.clone(),
|
||||
// DL6
|
||||
// IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone(),
|
||||
IDM_ACP_PEOPLE_CREATE_DL6.clone().into(),
|
||||
IDM_ACP_GROUP_MANAGE_DL6.clone().into(),
|
||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(),
|
||||
// IDM_ACP_DOMAIN_ADMIN_DL6.clone(),
|
||||
// DL7
|
||||
// IDM_ACP_SELF_WRITE_DL7.clone(),
|
||||
IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(),
|
||||
IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(),
|
||||
IDM_ACP_OAUTH2_MANAGE_DL7.clone().into(),
|
||||
// DL8
|
||||
IDM_ACP_SELF_READ_DL8.clone().into(),
|
||||
IDM_ACP_SELF_WRITE_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(),
|
||||
IDM_ACP_MAIL_SERVERS_DL8.clone().into(),
|
||||
IDM_ACP_DOMAIN_ADMIN_DL8.clone().into(),
|
||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(),
|
||||
]
|
||||
}
|
1506
server/lib/src/migration_data/dl8/schema.rs
Normal file
1506
server/lib/src/migration_data/dl8/schema.rs
Normal file
File diff suppressed because it is too large
Load diff
1073
server/lib/src/migration_data/dl8/system_config.rs
Normal file
1073
server/lib/src/migration_data/dl8/system_config.rs
Normal file
File diff suppressed because it is too large
Load diff
2637
server/lib/src/migration_data/dl9/access.rs
Normal file
2637
server/lib/src/migration_data/dl9/access.rs
Normal file
File diff suppressed because it is too large
Load diff
35
server/lib/src/migration_data/dl9/accounts.rs
Normal file
35
server/lib/src/migration_data/dl9/accounts.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
//! Constant Entries for the IDM
|
||||
use crate::constants::uuids::*;
|
||||
use crate::migration_data::types::BuiltinAccount;
|
||||
use kanidm_proto::v1::AccountType;
|
||||
|
||||
lazy_static! {
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "idm_admin",
|
||||
uuid: UUID_IDM_ADMIN,
|
||||
description: "Builtin IDM Admin account.",
|
||||
displayname: "IDM Administrator",
|
||||
};
|
||||
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "admin",
|
||||
uuid: UUID_ADMIN,
|
||||
description: "Builtin System Admin account.",
|
||||
displayname: "System Administrator",
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
name: "anonymous",
|
||||
uuid: UUID_ANONYMOUS,
|
||||
description: "Anonymous access account.",
|
||||
displayname: "Anonymous",
|
||||
};
|
||||
}
|
408
server/lib/src/migration_data/dl9/groups.rs
Normal file
408
server/lib/src/migration_data/dl9/groups.rs
Normal file
|
@ -0,0 +1,408 @@
|
|||
use crate::entry::EntryInitNew;
|
||||
use crate::prelude::*;
|
||||
use crate::value::CredentialType;
|
||||
|
||||
use kanidm_proto::internal::{Filter, OperationError, UiHint};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
/// Built-in group definitions
|
||||
pub struct BuiltinGroup {
|
||||
pub name: &'static str,
|
||||
pub description: &'static str,
|
||||
pub uuid: uuid::Uuid,
|
||||
pub members: Vec<uuid::Uuid>,
|
||||
pub entry_managed_by: Option<uuid::Uuid>,
|
||||
pub dyngroup: bool,
|
||||
pub dyngroup_filter: Option<Filter>,
|
||||
pub extra_attributes: Vec<(Attribute, Value)>,
|
||||
}
|
||||
|
||||
impl TryFrom<BuiltinGroup> for EntryInitNew {
|
||||
type Error = OperationError;
|
||||
|
||||
fn try_from(val: BuiltinGroup) -> Result<Self, OperationError> {
|
||||
let mut entry = EntryInitNew::new();
|
||||
|
||||
if val.uuid >= DYNAMIC_RANGE_MINIMUM_UUID {
|
||||
error!("Builtin ACP has invalid UUID! {:?}", val);
|
||||
return Err(OperationError::InvalidUuid);
|
||||
}
|
||||
|
||||
entry.add_ava(Attribute::Name, Value::new_iname(val.name));
|
||||
entry.add_ava(Attribute::Description, Value::new_utf8s(val.description));
|
||||
// classes for groups
|
||||
entry.set_ava(
|
||||
Attribute::Class,
|
||||
vec![EntryClass::Group.into(), EntryClass::Object.into()],
|
||||
);
|
||||
if val.dyngroup {
|
||||
if !val.members.is_empty() {
|
||||
return Err(OperationError::InvalidSchemaState(format!(
|
||||
"Builtin dyngroup {} has members specified, this is not allowed",
|
||||
val.name
|
||||
)));
|
||||
}
|
||||
entry.add_ava(Attribute::Class, EntryClass::DynGroup.to_value());
|
||||
match val.dyngroup_filter {
|
||||
Some(filter) => entry.add_ava(Attribute::DynGroupFilter, Value::JsonFilt(filter)),
|
||||
None => {
|
||||
error!(
|
||||
"No filter specified for dyngroup '{}' this is going to break things!",
|
||||
val.name
|
||||
);
|
||||
return Err(OperationError::FilterGeneration);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(entry_manager) = val.entry_managed_by {
|
||||
entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager));
|
||||
}
|
||||
|
||||
entry.add_ava(Attribute::Uuid, Value::Uuid(val.uuid));
|
||||
entry.set_ava(
|
||||
Attribute::Member,
|
||||
val.members
|
||||
.into_iter()
|
||||
.map(Value::Refer)
|
||||
.collect::<Vec<Value>>(),
|
||||
);
|
||||
// add any extra attributes
|
||||
val.extra_attributes
|
||||
.into_iter()
|
||||
.for_each(|(attr, val)| entry.add_ava(attr, val));
|
||||
// all done!
|
||||
Ok(entry)
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// There are our built in "roles". They encapsulate some higher level collections
|
||||
// of roles. The intent is to allow a pretty generic and correct by default set
|
||||
// of these use cases.
|
||||
pub static ref BUILTIN_GROUP_SYSTEM_ADMINS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: "system_admins",
|
||||
description: "Builtin System Administrators Group.",
|
||||
uuid: UUID_SYSTEM_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_ADMIN],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_IDM_ADMINS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_admins",
|
||||
description: "Builtin IDM Administrators Group.",
|
||||
uuid: UUID_IDM_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMIN],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_SERVICE_DESK: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_service_desk",
|
||||
description: "Builtin Service Desk Group.",
|
||||
uuid: UUID_IDM_SERVICE_DESK,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// These are the "finer" roles. They encapsulate different concepts in the system.
|
||||
// The next section is the "system style" roles. These adjust the operation of
|
||||
// kanidm and relate to it's internals and how it functions.
|
||||
pub static ref BUILTIN_GROUP_RECYCLE_BIN_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_recycle_bin_admins",
|
||||
description: "Builtin Recycle Bin Administrators Group.",
|
||||
uuid: UUID_IDM_RECYCLE_BIN_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting local domain administration rights and trust administration rights
|
||||
pub static ref BUILTIN_GROUP_DOMAIN_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "domain_admins",
|
||||
description: "Builtin IDM Group for granting local domain administration rights and trust administration rights.",
|
||||
uuid: UUID_DOMAIN_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_SCHEMA_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_schema_admins",
|
||||
description: "Builtin Schema Administration Group.",
|
||||
uuid: UUID_IDM_SCHEMA_ADMINS,
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_ACCESS_CONTROL_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_access_control_admins",
|
||||
description: "Builtin Access Control Administration Group.",
|
||||
entry_managed_by: Some(UUID_SYSTEM_ADMINS),
|
||||
uuid: UUID_IDM_ACCESS_CONTROL_ADMINS,
|
||||
members: vec![UUID_SYSTEM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// These are the IDM roles. They concern application integration, user permissions
|
||||
// and credential security management.
|
||||
|
||||
/// Builtin IDM Group for managing persons and their account details
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_admins",
|
||||
description: "Builtin People Administration Group.",
|
||||
uuid: UUID_IDM_PEOPLE_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_ON_BOARDING: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_on_boarding",
|
||||
description: "Builtin People On Boarding Group.",
|
||||
uuid: UUID_IDM_PEOPLE_ON_BOARDING,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting elevated people (personal data) read permissions.
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_PII_READ: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_pii_read",
|
||||
description: "Builtin IDM Group for granting elevated people (personal data) read permissions.",
|
||||
uuid: UUID_IDM_PEOPLE_PII_READ,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting people the ability to write to their own name attributes.
|
||||
pub static ref BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_self_name_write",
|
||||
description: "Builtin IDM Group denoting users that can write to their own name attributes.",
|
||||
uuid: UUID_IDM_PEOPLE_SELF_NAME_WRITE,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![
|
||||
UUID_IDM_ALL_PERSONS
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_service_account_admins",
|
||||
description: "Builtin Service Account Administration Group.",
|
||||
uuid: UUID_IDM_SERVICE_ACCOUNT_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain.
|
||||
pub static ref BUILTIN_GROUP_OAUTH2_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_oauth2_admins",
|
||||
description: "Builtin Oauth2 Integration Administration Group.",
|
||||
uuid: UUID_IDM_OAUTH2_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_RADIUS_SERVICE_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_radius_service_admins",
|
||||
description: "Builtin Radius Administration Group.",
|
||||
uuid: UUID_IDM_RADIUS_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for RADIUS server access delegation.
|
||||
pub static ref BUILTIN_IDM_RADIUS_SERVERS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_radius_servers",
|
||||
description: "Builtin IDM Group for RADIUS server access delegation.",
|
||||
uuid: UUID_IDM_RADIUS_SERVERS,
|
||||
entry_managed_by: Some(UUID_IDM_RADIUS_ADMINS),
|
||||
members: vec![
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_mail_service_admins",
|
||||
description: "Builtin Mail Server Administration Group.",
|
||||
uuid: UUID_IDM_MAIL_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for MAIL server Access delegation.
|
||||
pub static ref BUILTIN_IDM_MAIL_SERVERS_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_mail_servers",
|
||||
description: "Builtin IDM Group for MAIL server access delegation.",
|
||||
uuid: UUID_IDM_MAIL_SERVERS,
|
||||
entry_managed_by: Some(UUID_IDM_MAIL_ADMINS),
|
||||
members: vec![
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_account_policy_admins",
|
||||
description: "Builtin Account Policy Administration Group.",
|
||||
uuid: UUID_IDM_ACCOUNT_POLICY_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for managing posix/unix attributes on groups and users.
|
||||
pub static ref BUILTIN_GROUP_UNIX_ADMINS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_unix_admins",
|
||||
description: "Builtin Unix Administration Group.",
|
||||
uuid: UUID_IDM_UNIX_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for managing client authentication certificates.
|
||||
pub static ref BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_client_certificate_admins",
|
||||
description: "Builtin Client Certificate Administration Group.",
|
||||
uuid: UUID_IDM_CLIENT_CERTIFICATE_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Builtin IDM Group for granting elevated group write and lifecycle permissions.
|
||||
pub static ref IDM_GROUP_ADMINS_V1: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_group_admins",
|
||||
description: "Builtin IDM Group for granting elevated group write and lifecycle permissions.",
|
||||
uuid: UUID_IDM_GROUP_ADMINS,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Self-write of mail
|
||||
pub static ref IDM_PEOPLE_SELF_MAIL_WRITE_DL7: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_people_self_mail_write",
|
||||
description: "Builtin IDM Group for people accounts to update their own mail.",
|
||||
uuid: UUID_IDM_PEOPLE_SELF_MAIL_WRITE,
|
||||
members: Vec::with_capacity(0),
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
// at some point vs code just gives up on syntax highlighting inside lazy_static...
|
||||
lazy_static! {
|
||||
pub static ref IDM_ALL_PERSONS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_all_persons",
|
||||
description: "Builtin IDM dynamic group containing all persons.",
|
||||
uuid: UUID_IDM_ALL_PERSONS,
|
||||
members: Vec::with_capacity(0),
|
||||
dyngroup: true,
|
||||
dyngroup_filter: Some(
|
||||
Filter::And(vec![
|
||||
Filter::Eq(Attribute::Class.to_string(), EntryClass::Person.to_string()),
|
||||
Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()),
|
||||
])
|
||||
),
|
||||
extra_attributes: vec![
|
||||
// Enable account policy by default
|
||||
(Attribute::Class, EntryClass::AccountPolicy.to_value()),
|
||||
// Enforce this is a system protected object
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
// MFA By Default
|
||||
(Attribute::CredentialTypeMinimum, CredentialType::Mfa.into()),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref IDM_ALL_ACCOUNTS: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_all_accounts",
|
||||
description: "Builtin IDM dynamic group containing all entries that can authenticate.",
|
||||
uuid: UUID_IDM_ALL_ACCOUNTS,
|
||||
members: Vec::with_capacity(0),
|
||||
dyngroup: true,
|
||||
dyngroup_filter: Some(
|
||||
Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()),
|
||||
),
|
||||
extra_attributes: vec![
|
||||
// Enable account policy by default
|
||||
(Attribute::Class, EntryClass::AccountPolicy.to_value()),
|
||||
// Enforce this is a system protected object
|
||||
(Attribute::Class, EntryClass::System.to_value()),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
pub static ref IDM_UI_ENABLE_EXPERIMENTAL_FEATURES: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_ui_enable_experimental_features",
|
||||
description: "Members of this group will have access to experimental web UI features.",
|
||||
uuid: UUID_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES,
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
extra_attributes: vec![
|
||||
(Attribute::GrantUiHint, Value::UiHint(UiHint::ExperimentalFeatures))
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// Members of this group will have access to read the mail attribute of all persons and service accounts.
|
||||
pub static ref IDM_ACCOUNT_MAIL_READ: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_account_mail_read",
|
||||
description: "Members of this group will have access to read the mail attribute of all persons and service accounts.",
|
||||
entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS),
|
||||
uuid: UUID_IDM_ACCOUNT_MAIL_READ,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/// This must be the last group to init to include the UUID of the other high priv groups.
|
||||
pub static ref IDM_HIGH_PRIVILEGE_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_high_privilege",
|
||||
uuid: UUID_IDM_HIGH_PRIVILEGE,
|
||||
entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS),
|
||||
description: "Builtin IDM provided groups with high levels of access that should be audited and limited in modification.",
|
||||
members: vec![
|
||||
UUID_SYSTEM_ADMINS,
|
||||
UUID_IDM_ADMINS,
|
||||
UUID_DOMAIN_ADMINS,
|
||||
UUID_IDM_SERVICE_DESK,
|
||||
UUID_IDM_RECYCLE_BIN_ADMINS,
|
||||
UUID_IDM_SCHEMA_ADMINS,
|
||||
UUID_IDM_ACCESS_CONTROL_ADMINS,
|
||||
UUID_IDM_OAUTH2_ADMINS,
|
||||
UUID_IDM_RADIUS_ADMINS,
|
||||
UUID_IDM_ACCOUNT_POLICY_ADMINS,
|
||||
UUID_IDM_RADIUS_SERVERS,
|
||||
UUID_IDM_GROUP_ADMINS,
|
||||
UUID_IDM_UNIX_ADMINS,
|
||||
UUID_IDM_PEOPLE_PII_READ,
|
||||
UUID_IDM_PEOPLE_ADMINS,
|
||||
UUID_IDM_PEOPLE_ON_BOARDING,
|
||||
UUID_IDM_SERVICE_ACCOUNT_ADMINS,
|
||||
UUID_IDM_CLIENT_CERTIFICATE_ADMINS,
|
||||
UUID_IDM_APPLICATION_ADMINS,
|
||||
UUID_IDM_MAIL_ADMINS,
|
||||
UUID_IDM_HIGH_PRIVILEGE,
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref BUILTIN_GROUP_APPLICATION_ADMINS_DL8: BuiltinGroup = BuiltinGroup {
|
||||
name: "idm_application_admins",
|
||||
uuid: UUID_IDM_APPLICATION_ADMINS,
|
||||
description: "Builtin Application Administration Group.",
|
||||
entry_managed_by: Some(UUID_IDM_ADMINS),
|
||||
members: vec![UUID_IDM_ADMINS],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
18
server/lib/src/migration_data/dl9/key_providers.rs
Normal file
18
server/lib/src/migration_data/dl9/key_providers.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use crate::constants::entries::{Attribute, EntryClass};
|
||||
use crate::constants::uuids::UUID_KEY_PROVIDER_INTERNAL;
|
||||
use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew};
|
||||
use crate::value::Value;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref E_KEY_PROVIDER_INTERNAL_DL6: EntryInitNew = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyProvider.to_value()),
|
||||
(Attribute::Class, EntryClass::KeyProviderInternal.to_value()),
|
||||
(Attribute::Uuid, Value::Uuid(UUID_KEY_PROVIDER_INTERNAL)),
|
||||
(Attribute::Name, Value::new_iname("key_provider_internal")),
|
||||
(
|
||||
Attribute::Description,
|
||||
Value::new_utf8s("The default database internal cryptographic key provider.")
|
||||
)
|
||||
);
|
||||
}
|
264
server/lib/src/migration_data/dl9/mod.rs
Normal file
264
server/lib/src/migration_data/dl9/mod.rs
Normal file
|
@ -0,0 +1,264 @@
|
|||
mod access;
|
||||
mod accounts;
|
||||
mod groups;
|
||||
mod key_providers;
|
||||
mod schema;
|
||||
mod system_config;
|
||||
|
||||
use self::access::*;
|
||||
use self::accounts::*;
|
||||
use self::groups::*;
|
||||
use self::key_providers::*;
|
||||
use self::schema::*;
|
||||
use self::system_config::*;
|
||||
|
||||
use crate::prelude::EntryInitNew;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
|
||||
pub fn phase_1_schema_attrs() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(),
|
||||
SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(),
|
||||
SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(),
|
||||
SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_NAME.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_SSID.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_UUID.clone().into(),
|
||||
SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(),
|
||||
SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(),
|
||||
SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(),
|
||||
SCHEMA_ATTR_GIDNUMBER.clone().into(),
|
||||
SCHEMA_ATTR_GRANT_UI_HINT.clone().into(),
|
||||
SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_LOGINSHELL.clone().into(),
|
||||
SCHEMA_ATTR_NAME_HISTORY.clone().into(),
|
||||
SCHEMA_ATTR_NSUNIQUEID.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
|
||||
.clone()
|
||||
.into(),
|
||||
SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(),
|
||||
SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_RADIUS_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_COOKIE.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_UNIX_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_DENIED_NAME.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(),
|
||||
SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4
|
||||
.clone()
|
||||
.into(),
|
||||
// DL5
|
||||
// DL6
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(),
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(),
|
||||
// DL7
|
||||
SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(),
|
||||
SCHEMA_ATTR_REFERS_DL7.clone().into(),
|
||||
SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(),
|
||||
SCHEMA_ATTR_MAIL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_LEGALNAME_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(),
|
||||
SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(),
|
||||
SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(),
|
||||
// DL9
|
||||
SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_2_schema_classes() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
SCHEMA_CLASS_DYNGROUP.clone().into(),
|
||||
SCHEMA_CLASS_ORGPERSON.clone().into(),
|
||||
SCHEMA_CLASS_POSIXACCOUNT.clone().into(),
|
||||
SCHEMA_CLASS_POSIXGROUP.clone().into(),
|
||||
SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(),
|
||||
// DL5
|
||||
SCHEMA_CLASS_ACCOUNT_DL5.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(),
|
||||
// DL6
|
||||
SCHEMA_CLASS_GROUP_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(),
|
||||
// DL7
|
||||
SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(),
|
||||
SCHEMA_CLASS_APPLICATION_DL8.clone().into(),
|
||||
SCHEMA_CLASS_PERSON_DL8.clone().into(),
|
||||
// DL9
|
||||
SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(),
|
||||
SCHEMA_CLASS_DOMAIN_INFO_DL9.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_3_key_provider() -> Vec<EntryInitNew> {
|
||||
vec![E_KEY_PROVIDER_INTERNAL_DL6.clone()]
|
||||
}
|
||||
|
||||
pub fn phase_4_system_entries() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
E_SYSTEM_INFO_V1.clone(),
|
||||
E_DOMAIN_INFO_DL6.clone(),
|
||||
E_SYSTEM_CONFIG_V1.clone(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn phase_5_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
Ok(vec![
|
||||
BUILTIN_ACCOUNT_ADMIN.clone().into(),
|
||||
BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(),
|
||||
BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?,
|
||||
BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?,
|
||||
// We need to push anonymous *after* groups due to entry-managed-by
|
||||
BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn phase_6_builtin_non_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||
Ok(vec![
|
||||
BUILTIN_GROUP_DOMAIN_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_SCHEMA_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_ACCESS_CONTROL_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_UNIX_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_RECYCLE_BIN_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_SERVICE_DESK.clone().try_into()?,
|
||||
BUILTIN_GROUP_OAUTH2_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_RADIUS_SERVICE_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_PII_READ.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_ON_BOARDING.clone().try_into()?,
|
||||
BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS.clone().try_into()?,
|
||||
BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8.clone().try_into()?,
|
||||
IDM_GROUP_ADMINS_V1.clone().try_into()?,
|
||||
IDM_ALL_PERSONS.clone().try_into()?,
|
||||
IDM_ALL_ACCOUNTS.clone().try_into()?,
|
||||
BUILTIN_IDM_RADIUS_SERVERS_V1.clone().try_into()?,
|
||||
BUILTIN_IDM_MAIL_SERVERS_DL8.clone().try_into()?,
|
||||
BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7
|
||||
.clone()
|
||||
.try_into()?,
|
||||
IDM_PEOPLE_SELF_MAIL_WRITE_DL7.clone().try_into()?,
|
||||
BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7
|
||||
.clone()
|
||||
.try_into()?,
|
||||
BUILTIN_GROUP_APPLICATION_ADMINS_DL8.clone().try_into()?,
|
||||
// Write deps on read.clone().try_into()?, so write must be added first.
|
||||
// All members must exist before we write HP
|
||||
IDM_HIGH_PRIVILEGE_DL8.clone().try_into()?,
|
||||
// other things
|
||||
IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone().try_into()?,
|
||||
IDM_ACCOUNT_MAIL_READ.clone().try_into()?,
|
||||
])
|
||||
}
|
||||
|
||||
pub fn phase_7_builtin_access_control_profiles() -> Vec<EntryInitNew> {
|
||||
vec![
|
||||
// Built in access controls.
|
||||
IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(),
|
||||
IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(),
|
||||
IDM_ACP_ACP_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SERVERS_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(),
|
||||
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(),
|
||||
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(),
|
||||
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_GROUP_READ_V1.clone().into(),
|
||||
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_DELETE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
// DL4
|
||||
// DL5
|
||||
// DL6
|
||||
IDM_ACP_PEOPLE_CREATE_DL6.clone().into(),
|
||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(),
|
||||
// DL7
|
||||
IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(),
|
||||
IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(),
|
||||
// DL8
|
||||
IDM_ACP_SELF_READ_DL8.clone().into(),
|
||||
IDM_ACP_SELF_WRITE_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(),
|
||||
IDM_ACP_MAIL_SERVERS_DL8.clone().into(),
|
||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(),
|
||||
// DL9
|
||||
IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(),
|
||||
IDM_ACP_GROUP_MANAGE_DL9.clone().into(),
|
||||
IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(),
|
||||
]
|
||||
}
|
1506
server/lib/src/migration_data/dl9/schema.rs
Normal file
1506
server/lib/src/migration_data/dl9/schema.rs
Normal file
File diff suppressed because it is too large
Load diff
1073
server/lib/src/migration_data/dl9/system_config.rs
Normal file
1073
server/lib/src/migration_data/dl9/system_config.rs
Normal file
File diff suppressed because it is too large
Load diff
24
server/lib/src/migration_data/mod.rs
Normal file
24
server/lib/src/migration_data/mod.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
pub(crate) mod dl10;
|
||||
pub(crate) mod dl8;
|
||||
pub(crate) mod dl9;
|
||||
|
||||
mod types;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) use dl10::accounts::BUILTIN_ACCOUNT_ANONYMOUS_DL6 as BUILTIN_ACCOUNT_ANONYMOUS;
|
||||
|
||||
#[cfg(test)]
|
||||
use self::types::BuiltinAccount;
|
||||
|
||||
#[cfg(test)]
|
||||
lazy_static! {
|
||||
/// Builtin System Admin account.
|
||||
pub static ref BUILTIN_ACCOUNT_TEST_PERSON: BuiltinAccount = BuiltinAccount {
|
||||
account_type: kanidm_proto::v1::AccountType::Person,
|
||||
entry_managed_by: None,
|
||||
name: "test_person",
|
||||
uuid: crate::constants::uuids::UUID_TESTPERSON_1,
|
||||
description: "Test Person",
|
||||
displayname: "Test Person",
|
||||
};
|
||||
}
|
83
server/lib/src/migration_data/types.rs
Normal file
83
server/lib/src/migration_data/types.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
//! Constant Entries for the IDM
|
||||
use crate::constants::uuids::*;
|
||||
use crate::entry::EntryInitNew;
|
||||
use crate::prelude::EntryClass;
|
||||
use crate::value::Value;
|
||||
pub use kanidm_proto::attribute::Attribute;
|
||||
use kanidm_proto::v1::AccountType;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Built in accounts such as anonymous, idm_admin and admin
|
||||
pub struct BuiltinAccount {
|
||||
pub account_type: kanidm_proto::v1::AccountType,
|
||||
pub entry_managed_by: Option<uuid::Uuid>,
|
||||
pub name: &'static str,
|
||||
pub uuid: Uuid,
|
||||
pub description: &'static str,
|
||||
pub displayname: &'static str,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl Default for BuiltinAccount {
|
||||
fn default() -> Self {
|
||||
BuiltinAccount {
|
||||
account_type: AccountType::ServiceAccount,
|
||||
entry_managed_by: None,
|
||||
name: "",
|
||||
uuid: Uuid::new_v4(),
|
||||
description: "<set description>",
|
||||
displayname: "<set displayname>",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl From<BuiltinAccount> for crate::idm::account::Account {
|
||||
fn from(value: BuiltinAccount) -> Self {
|
||||
Self {
|
||||
name: value.name.to_string(),
|
||||
uuid: value.uuid,
|
||||
displayname: value.displayname.to_string(),
|
||||
spn: format!("{}@example.com", value.name),
|
||||
mail_primary: None,
|
||||
mail: Vec::with_capacity(0),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BuiltinAccount> for EntryInitNew {
|
||||
fn from(value: BuiltinAccount) -> Self {
|
||||
let mut entry = EntryInitNew::new();
|
||||
entry.add_ava(Attribute::Name, Value::new_iname(value.name));
|
||||
#[allow(clippy::panic)]
|
||||
if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID {
|
||||
panic!("Builtin ACP has invalid UUID! {:?}", value);
|
||||
}
|
||||
entry.add_ava(Attribute::Uuid, Value::Uuid(value.uuid));
|
||||
entry.add_ava(Attribute::Description, Value::new_utf8s(value.description));
|
||||
entry.add_ava(Attribute::DisplayName, Value::new_utf8s(value.displayname));
|
||||
|
||||
if let Some(entry_manager) = value.entry_managed_by {
|
||||
entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager));
|
||||
}
|
||||
|
||||
entry.set_ava(
|
||||
Attribute::Class,
|
||||
vec![
|
||||
EntryClass::Account.to_value(),
|
||||
EntryClass::MemberOf.to_value(),
|
||||
EntryClass::Object.to_value(),
|
||||
],
|
||||
);
|
||||
match value.account_type {
|
||||
AccountType::Person => entry.add_ava(Attribute::Class, EntryClass::Person.to_value()),
|
||||
AccountType::ServiceAccount => {
|
||||
entry.add_ava(Attribute::Class, EntryClass::ServiceAccount.to_value())
|
||||
}
|
||||
}
|
||||
entry
|
||||
}
|
||||
}
|
|
@ -571,35 +571,43 @@ impl Plugin for MemberOf {
|
|||
Err(e) => return vec![e],
|
||||
};
|
||||
|
||||
// First we have to build a direct membership map. This saves us
|
||||
// needing to run queries since we already have every entry on hand
|
||||
// from the all_cand search.
|
||||
let mut direct_membership_map: BTreeMap<Uuid, BTreeSet<Uuid>> = Default::default();
|
||||
|
||||
let pv_class: PartialValue = EntryClass::Group.into();
|
||||
|
||||
for entry in all_cand.iter() {
|
||||
if !entry.attribute_equality(Attribute::Class, &pv_class) {
|
||||
// Not a group, move on.
|
||||
continue;
|
||||
}
|
||||
|
||||
let group_uuid = entry.get_uuid();
|
||||
|
||||
let member_iter = entry
|
||||
.get_ava_refer(Attribute::Member)
|
||||
.into_iter()
|
||||
.flat_map(|set| set.iter())
|
||||
.chain(
|
||||
entry
|
||||
.get_ava_refer(Attribute::DynMember)
|
||||
.into_iter()
|
||||
.flat_map(|set| set.iter()),
|
||||
);
|
||||
|
||||
for member_uuid in member_iter {
|
||||
let member_groups = direct_membership_map.entry(*member_uuid).or_default();
|
||||
member_groups.insert(group_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
// for each entry in the DB (live).
|
||||
for e in all_cand {
|
||||
let uuid = e.get_uuid();
|
||||
let filt_in = filter!(f_and!([
|
||||
f_eq(Attribute::Class, EntryClass::Group.into()),
|
||||
f_or!([
|
||||
f_eq(Attribute::Member, PartialValue::Refer(uuid)),
|
||||
f_eq(Attribute::DynMember, PartialValue::Refer(uuid))
|
||||
])
|
||||
]));
|
||||
|
||||
// what groups is this entry a direct member of?
|
||||
let direct_memberof = match qs
|
||||
.internal_search(filt_in)
|
||||
.map_err(|_| ConsistencyError::QueryServerSearchFailure)
|
||||
{
|
||||
Ok(d_mo) => d_mo,
|
||||
Err(e) => return vec![Err(e)],
|
||||
};
|
||||
|
||||
// for all direct -> add uuid to map
|
||||
let d_groups_set: BTreeSet<Uuid> =
|
||||
direct_memberof.iter().map(|e| e.get_uuid()).collect();
|
||||
|
||||
let d_groups_set = if d_groups_set.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(d_groups_set)
|
||||
};
|
||||
let d_groups_set: Option<&BTreeSet<Uuid>> = direct_membership_map.get(&uuid);
|
||||
|
||||
trace!(
|
||||
"DMO search groups {:?} -> {:?}",
|
||||
|
@ -607,12 +615,16 @@ impl Plugin for MemberOf {
|
|||
d_groups_set
|
||||
);
|
||||
|
||||
// Remember, we only need to check direct memberships, because when memberof
|
||||
// it applies it clones dmo -> mo, so validation of all dmo sets implies mo is
|
||||
// valid (and a subset) of dmo.
|
||||
|
||||
match (e.get_ava_set(Attribute::DirectMemberOf), d_groups_set) {
|
||||
(Some(edmos), Some(b)) => {
|
||||
// Can they both be reference sets?
|
||||
match edmos.as_refer_set() {
|
||||
Some(a) => {
|
||||
let diff: Vec<_> = a.symmetric_difference(&b).collect();
|
||||
let diff: Vec<_> = a.symmetric_difference(b).collect();
|
||||
if !diff.is_empty() {
|
||||
error!(
|
||||
"MemberOfInvalid: Entry {}, DMO has inconsistencies",
|
||||
|
@ -636,7 +648,7 @@ impl Plugin for MemberOf {
|
|||
}
|
||||
(entry_direct_member_of, expected_direct_groups) => {
|
||||
error!(
|
||||
"MemberOfInvalid directmemberof set and DMO search set differ in size: {}",
|
||||
"MemberOfInvalid directmemberof set and DMO search set differ in presence: {}",
|
||||
e.get_display_id()
|
||||
);
|
||||
// trace!(?e);
|
||||
|
@ -645,19 +657,6 @@ impl Plugin for MemberOf {
|
|||
r.push(Err(ConsistencyError::MemberOfInvalid(e.get_id())));
|
||||
}
|
||||
}
|
||||
|
||||
// Could check all dmos in mos?
|
||||
|
||||
/* To check nested! */
|
||||
// add all direct to a stack
|
||||
// for all in stack
|
||||
// check their direct memberships
|
||||
// if not in map
|
||||
// add to map
|
||||
// push to stack
|
||||
|
||||
// check mo == map set
|
||||
// if not, consistency error!
|
||||
}
|
||||
|
||||
r
|
||||
|
|
|
@ -1159,6 +1159,7 @@ mod tests {
|
|||
},
|
||||
Access, AccessClass, AccessControls, AccessControlsTransaction, AccessEffectivePermission,
|
||||
};
|
||||
use crate::migration_data::BUILTIN_ACCOUNT_ANONYMOUS;
|
||||
use crate::prelude::*;
|
||||
use crate::valueset::ValueSetIname;
|
||||
|
||||
|
@ -2511,6 +2512,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_access_enforce_scope_delete() {
|
||||
sketching::test_init();
|
||||
let ev1 = E_TESTPERSON_1.clone().into_sealed_committed();
|
||||
let r_set = vec![Arc::new(ev1)];
|
||||
|
||||
|
@ -3052,7 +3054,7 @@ mod tests {
|
|||
test_acp_search_reduce!(&se_a, vec![], r_set.clone(), ex_a_reduced);
|
||||
|
||||
// Check that anonymous is denied even though it's a member of the group.
|
||||
let anon: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||
let anon: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS.clone().into();
|
||||
let mut anon = anon.into_invalid_new();
|
||||
anon.set_ava_set(&Attribute::MemberOf, ValueSetRefer::new(UUID_TEST_GROUP_1));
|
||||
|
||||
|
@ -3352,7 +3354,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_access_delete_protect_system_ranges() {
|
||||
let ev1: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||
let ev1: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS.clone().into();
|
||||
let ev1 = ev1.into_sealed_committed();
|
||||
let r_set = vec![Arc::new(ev1)];
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
use crate::migration_data;
|
||||
use kanidm_proto::internal::{
|
||||
DomainUpgradeCheckItem as ProtoDomainUpgradeCheckItem,
|
||||
DomainUpgradeCheckReport as ProtoDomainUpgradeCheckReport,
|
||||
|
@ -48,17 +49,24 @@ impl QueryServer {
|
|||
debug!(?db_domain_version, "Before setting internal domain info");
|
||||
|
||||
if db_domain_version == 0 {
|
||||
// No domain info was present, so neither was the rest of the IDM. We need to bootstrap
|
||||
// the base-schema here.
|
||||
write_txn.initialise_schema_idm()?;
|
||||
// This is here to catch when we increase domain levels but didn't create the migration
|
||||
// hooks. If this fails it probably means you need to add another migration hook
|
||||
// in the above.
|
||||
debug_assert!(domain_target_level <= DOMAIN_MAX_LEVEL);
|
||||
|
||||
write_txn.reload()?;
|
||||
|
||||
// Since we just loaded in a ton of schema, lets reindex it to make
|
||||
// sure that some base IDM operations are fast. Since this is still
|
||||
// very early in the bootstrap process, and very few entries exist,
|
||||
// reindexing is very fast here.
|
||||
write_txn.reindex(false)?;
|
||||
// No domain info was present, so neither was the rest of the IDM. Bring up the
|
||||
// full IDM here.
|
||||
match domain_target_level {
|
||||
DOMAIN_LEVEL_8 => write_txn.migrate_domain_7_to_8()?,
|
||||
DOMAIN_LEVEL_9 => write_txn.migrate_domain_8_to_9()?,
|
||||
DOMAIN_LEVEL_10 => write_txn.migrate_domain_9_to_10()?,
|
||||
DOMAIN_LEVEL_11 => write_txn.migrate_domain_10_to_11()?,
|
||||
_ => {
|
||||
error!("Invalid requested domain target level for server bootstrap");
|
||||
debug_assert!(false);
|
||||
return Err(OperationError::MG0009InvalidTargetLevelForBootstrap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Domain info was present, so we need to reflect that in our server
|
||||
// domain structures. If we don't do this, the in memory domain level
|
||||
|
@ -71,23 +79,11 @@ impl QueryServer {
|
|||
write_txn.force_domain_reload();
|
||||
|
||||
write_txn.reload()?;
|
||||
}
|
||||
|
||||
// Indicate the schema is now ready, which allows dyngroups to work when they
|
||||
// are created in the next phase of migrations.
|
||||
write_txn.set_phase(ServerPhase::SchemaReady);
|
||||
// Indicate the schema is now ready, which allows dyngroups to work when they
|
||||
// are created in the next phase of migrations.
|
||||
write_txn.set_phase(ServerPhase::SchemaReady);
|
||||
|
||||
// No domain info was present, so neither was the rest of the IDM. We need to bootstrap
|
||||
// the base entries here.
|
||||
if db_domain_version == 0 {
|
||||
// Init idm will now set the system config version and minimum domain
|
||||
// level if none was present
|
||||
write_txn.initialise_domain_info()?;
|
||||
|
||||
// In this path because we create the dyn groups they are immediately added to the
|
||||
// dyngroup cache and begin to operate.
|
||||
write_txn.initialise_idm()?;
|
||||
} else {
|
||||
// #2756 - if we *aren't* creating the base IDM entries, then we
|
||||
// need to force dyn groups to reload since we're now at schema
|
||||
// ready. This is done indirectly by ... reloading the schema again.
|
||||
|
@ -97,13 +93,13 @@ impl QueryServer {
|
|||
// itself or a change to schema reloading. Since we aren't changing the
|
||||
// dyngroup here, we have to go via the schema reload path.
|
||||
write_txn.force_schema_reload();
|
||||
};
|
||||
|
||||
// Reload as init idm affects access controls.
|
||||
write_txn.reload()?;
|
||||
// Reload as init idm affects access controls.
|
||||
write_txn.reload()?;
|
||||
|
||||
// Domain info is now ready and reloaded, we can proceed.
|
||||
write_txn.set_phase(ServerPhase::DomainInfoReady);
|
||||
// Domain info is now ready and reloaded, we can proceed.
|
||||
write_txn.set_phase(ServerPhase::DomainInfoReady);
|
||||
}
|
||||
|
||||
// This is the start of domain info related migrations which we will need in future
|
||||
// to handle replication. Due to the access control rework, and the addition of "managed by"
|
||||
|
@ -126,20 +122,18 @@ impl QueryServer {
|
|||
// If the database domain info is a lower version than our target level, we reload.
|
||||
if domain_info_version < domain_target_level {
|
||||
write_txn
|
||||
.internal_modify_uuid(
|
||||
UUID_DOMAIN_INFO,
|
||||
&ModifyList::new_purge_and_set(
|
||||
Attribute::Version,
|
||||
Value::new_uint32(domain_target_level),
|
||||
),
|
||||
)
|
||||
.internal_apply_domain_migration(domain_target_level)
|
||||
.map(|()| {
|
||||
warn!("Domain level has been raised to {}", domain_target_level);
|
||||
})?;
|
||||
|
||||
// Reload if anything in migrations requires it - this triggers the domain migrations
|
||||
// which in turn can trigger schema reloads etc.
|
||||
reload_required = true;
|
||||
// which in turn can trigger schema reloads etc. If the server was just brought up
|
||||
// then we don't need the extra reload since we are already at the correct
|
||||
// version of the server, and this call to set the target level is just for persistance
|
||||
// of the value.
|
||||
if domain_info_version != 0 {
|
||||
reload_required = true;
|
||||
}
|
||||
} else if domain_development_taint {
|
||||
// This forces pre-release versions to re-migrate each start up. This solves
|
||||
// the domain-version-sprawl issue so that during a development cycle we can
|
||||
|
@ -182,9 +176,6 @@ impl QueryServer {
|
|||
// we would have skipped the patch level fix which needs to have occurred *first*.
|
||||
if reload_required {
|
||||
write_txn.reload()?;
|
||||
// We are not yet at the schema phase where reindexes will auto-trigger
|
||||
// so if one was required, do it now.
|
||||
write_txn.reindex(false)?;
|
||||
}
|
||||
|
||||
// Now set the db/domain devel taint flag to match our current release status
|
||||
|
@ -206,7 +197,8 @@ impl QueryServer {
|
|||
// We are ready to run
|
||||
write_txn.set_phase(ServerPhase::Running);
|
||||
|
||||
// Commit all changes, this also triggers the reload.
|
||||
// Commit all changes, this also triggers the final reload, this should be a no-op
|
||||
// since we already did all the needed loads above.
|
||||
write_txn.commit()?;
|
||||
|
||||
debug!("Database version check and migrations success! ☀️ ");
|
||||
|
@ -217,7 +209,6 @@ impl QueryServer {
|
|||
impl QueryServerWriteTransaction<'_> {
|
||||
/// Apply a domain migration `to_level`. Panics if `to_level` is not greater than the active
|
||||
/// level.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn internal_apply_domain_migration(
|
||||
&mut self,
|
||||
to_level: u32,
|
||||
|
@ -230,6 +221,23 @@ impl QueryServerWriteTransaction<'_> {
|
|||
.and_then(|()| self.reload())
|
||||
}
|
||||
|
||||
fn internal_migrate_or_create_batch(
|
||||
&mut self,
|
||||
msg: &str,
|
||||
entries: Vec<EntryInitNew>,
|
||||
) -> Result<(), OperationError> {
|
||||
let r: Result<(), _> = entries
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry));
|
||||
|
||||
if let Err(err) = r {
|
||||
error!(?err, msg);
|
||||
debug_assert!(false);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
/// - If the thing exists:
|
||||
/// - Ensure the set of attributes match and are present
|
||||
|
@ -240,7 +248,7 @@ impl QueryServerWriteTransaction<'_> {
|
|||
/// This will extra classes an attributes alone!
|
||||
///
|
||||
/// NOTE: `gen_modlist*` IS schema aware and will handle multivalue correctly!
|
||||
pub fn internal_migrate_or_create(
|
||||
fn internal_migrate_or_create(
|
||||
&mut self,
|
||||
e: Entry<EntryInit, EntryNew>,
|
||||
) -> Result<(), OperationError> {
|
||||
|
@ -251,7 +259,7 @@ impl QueryServerWriteTransaction<'_> {
|
|||
/// list of attributes, so that if an admin has modified those values then we don't
|
||||
/// stomp them.
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub fn internal_migrate_or_create_ignore_attrs(
|
||||
fn internal_migrate_or_create_ignore_attrs(
|
||||
&mut self,
|
||||
mut e: Entry<EntryInit, EntryNew>,
|
||||
attrs: &[Attribute],
|
||||
|
@ -294,6 +302,75 @@ impl QueryServerWriteTransaction<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Migration domain level 7 to 8 (1.4.0)
|
||||
#[instrument(level = "info", skip_all)]
|
||||
pub(crate) fn migrate_domain_7_to_8(&mut self) -> Result<(), OperationError> {
|
||||
if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_9 {
|
||||
error!("Unable to raise domain level from 8 to 9.");
|
||||
return Err(OperationError::MG0004DomainLevelInDevelopment);
|
||||
}
|
||||
|
||||
// =========== Apply changes ==============
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 1 - schema attrs",
|
||||
migration_data::dl8::phase_1_schema_attrs(),
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 2 - schema classes",
|
||||
migration_data::dl8::phase_2_schema_classes(),
|
||||
)?;
|
||||
|
||||
// Reload for the new schema.
|
||||
self.reload()?;
|
||||
|
||||
// Reindex?
|
||||
self.reindex(false)?;
|
||||
|
||||
// Set Phase
|
||||
self.set_phase(ServerPhase::SchemaReady);
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 3 - key provider",
|
||||
migration_data::dl8::phase_3_key_provider(),
|
||||
)?;
|
||||
|
||||
// Reload for the new key providers
|
||||
self.reload()?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 4 - system entries",
|
||||
migration_data::dl8::phase_4_system_entries(),
|
||||
)?;
|
||||
|
||||
// Reload for the new system entries
|
||||
self.reload()?;
|
||||
|
||||
// Domain info is now ready and reloaded, we can proceed.
|
||||
self.set_phase(ServerPhase::DomainInfoReady);
|
||||
|
||||
// Bring up the IDM entries.
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 5 - builtin admin entries",
|
||||
migration_data::dl8::phase_5_builtin_admin_entries()?,
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 6 - builtin not admin entries",
|
||||
migration_data::dl8::phase_6_builtin_non_admin_entries()?,
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 7 - builtin access control profiles",
|
||||
migration_data::dl8::phase_7_builtin_access_control_profiles(),
|
||||
)?;
|
||||
|
||||
// Reload for all new access controls.
|
||||
self.reload()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Migration domain level 8 to 9 (1.5.0)
|
||||
#[instrument(level = "info", skip_all)]
|
||||
pub(crate) fn migrate_domain_8_to_9(&mut self) -> Result<(), OperationError> {
|
||||
|
@ -303,39 +380,61 @@ impl QueryServerWriteTransaction<'_> {
|
|||
}
|
||||
|
||||
// =========== Apply changes ==============
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 1 - schema attrs",
|
||||
migration_data::dl9::phase_1_schema_attrs(),
|
||||
)?;
|
||||
|
||||
// Now update schema
|
||||
let idm_schema_changes = [
|
||||
SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(),
|
||||
SCHEMA_CLASS_DOMAIN_INFO_DL9.clone().into(),
|
||||
];
|
||||
|
||||
idm_schema_changes
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
||||
.map_err(|err| {
|
||||
error!(?err, "migrate_domain_8_to_9 -> Error");
|
||||
err
|
||||
})?;
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 2 - schema classes",
|
||||
migration_data::dl9::phase_2_schema_classes(),
|
||||
)?;
|
||||
|
||||
// Reload for the new schema.
|
||||
self.reload()?;
|
||||
|
||||
let idm_data = [
|
||||
IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(),
|
||||
IDM_ACP_GROUP_MANAGE_DL9.clone().into(),
|
||||
IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(),
|
||||
];
|
||||
// Reindex?
|
||||
self.reindex(false)?;
|
||||
|
||||
idm_data
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
||||
.map_err(|err| {
|
||||
error!(?err, "migrate_domain_8_to_9 -> Error");
|
||||
err
|
||||
})?;
|
||||
// Set Phase
|
||||
self.set_phase(ServerPhase::SchemaReady);
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 3 - key provider",
|
||||
migration_data::dl9::phase_3_key_provider(),
|
||||
)?;
|
||||
|
||||
// Reload for the new key providers
|
||||
self.reload()?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 4 - system entries",
|
||||
migration_data::dl9::phase_4_system_entries(),
|
||||
)?;
|
||||
|
||||
// Reload for the new system entries
|
||||
self.reload()?;
|
||||
|
||||
// Domain info is now ready and reloaded, we can proceed.
|
||||
self.set_phase(ServerPhase::DomainInfoReady);
|
||||
|
||||
// Bring up the IDM entries.
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 5 - builtin admin entries",
|
||||
migration_data::dl9::phase_5_builtin_admin_entries()?,
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 6 - builtin not admin entries",
|
||||
migration_data::dl9::phase_6_builtin_non_admin_entries()?,
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 7 - builtin access control profiles",
|
||||
migration_data::dl9::phase_7_builtin_access_control_profiles(),
|
||||
)?;
|
||||
|
||||
// Reload for all new access controls.
|
||||
self.reload()?;
|
||||
|
||||
Ok(())
|
||||
|
@ -350,58 +449,7 @@ impl QueryServerWriteTransaction<'_> {
|
|||
|
||||
debug_assert!(*self.phase >= ServerPhase::SchemaReady);
|
||||
|
||||
let idm_data = [
|
||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(),
|
||||
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(),
|
||||
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(),
|
||||
IDM_ACP_ACP_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(),
|
||||
IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(),
|
||||
IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(),
|
||||
IDM_ACP_DOMAIN_ADMIN_DL8.clone().into(),
|
||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_GROUP_MANAGE_DL6.clone().into(),
|
||||
IDM_ACP_GROUP_READ_V1.clone().into(),
|
||||
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(),
|
||||
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_MAIL_SERVERS_DL8.clone().into(),
|
||||
IDM_ACP_OAUTH2_MANAGE_DL7.clone().into(),
|
||||
IDM_ACP_PEOPLE_CREATE_DL6.clone().into(),
|
||||
IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_DELETE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_PII_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_READ_V1.clone().into(),
|
||||
IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_RADIUS_SERVERS_V1.clone().into(),
|
||||
IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(),
|
||||
IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(),
|
||||
IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(),
|
||||
IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(),
|
||||
IDM_ACP_SELF_READ_DL8.clone().into(),
|
||||
IDM_ACP_SELF_WRITE_DL8.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1
|
||||
.clone()
|
||||
.into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(),
|
||||
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1
|
||||
.clone()
|
||||
.into(),
|
||||
];
|
||||
let idm_data = migration_data::dl9::phase_7_builtin_access_control_profiles();
|
||||
|
||||
idm_data
|
||||
.into_iter()
|
||||
|
@ -425,21 +473,62 @@ impl QueryServerWriteTransaction<'_> {
|
|||
}
|
||||
|
||||
// =========== Apply changes ==============
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 1 - schema attrs",
|
||||
migration_data::dl10::phase_1_schema_attrs(),
|
||||
)?;
|
||||
|
||||
// Now update schema
|
||||
let idm_schema_changes = [
|
||||
SCHEMA_ATTR_DENIED_NAME_DL10.clone().into(),
|
||||
SCHEMA_CLASS_DOMAIN_INFO_DL10.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES.clone().into(),
|
||||
];
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 2 - schema classes",
|
||||
migration_data::dl10::phase_2_schema_classes(),
|
||||
)?;
|
||||
|
||||
idm_schema_changes
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
||||
.map_err(|err| {
|
||||
error!(?err, "migrate_domain_9_to_10 -> Error");
|
||||
err
|
||||
})?;
|
||||
// Reload for the new schema.
|
||||
self.reload()?;
|
||||
|
||||
// Since we just loaded in a ton of schema, lets reindex it incase we added
|
||||
// new indexes, or this is a bootstrap and we have no indexes yet.
|
||||
self.reindex(false)?;
|
||||
|
||||
// Set Phase
|
||||
// Indicate the schema is now ready, which allows dyngroups to work when they
|
||||
// are created in the next phase of migrations.
|
||||
self.set_phase(ServerPhase::SchemaReady);
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 3 - key provider",
|
||||
migration_data::dl10::phase_3_key_provider(),
|
||||
)?;
|
||||
|
||||
// Reload for the new key providers
|
||||
self.reload()?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 4 - system entries",
|
||||
migration_data::dl10::phase_4_system_entries(),
|
||||
)?;
|
||||
|
||||
// Reload for the new system entries
|
||||
self.reload()?;
|
||||
|
||||
// Domain info is now ready and reloaded, we can proceed.
|
||||
self.set_phase(ServerPhase::DomainInfoReady);
|
||||
|
||||
// Bring up the IDM entries.
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 5 - builtin admin entries",
|
||||
migration_data::dl10::phase_5_builtin_admin_entries()?,
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 6 - builtin not admin entries",
|
||||
migration_data::dl10::phase_6_builtin_non_admin_entries()?,
|
||||
)?;
|
||||
|
||||
self.internal_migrate_or_create_batch(
|
||||
"phase 7 - builtin access control profiles",
|
||||
migration_data::dl10::phase_7_builtin_access_control_profiles(),
|
||||
)?;
|
||||
|
||||
self.reload()?;
|
||||
|
||||
|
@ -458,7 +547,7 @@ impl QueryServerWriteTransaction<'_> {
|
|||
}
|
||||
|
||||
#[instrument(level = "info", skip_all)]
|
||||
pub fn initialise_schema_core(&mut self) -> Result<(), OperationError> {
|
||||
pub(crate) fn initialise_schema_core(&mut self) -> Result<(), OperationError> {
|
||||
admin_debug!("initialise_schema_core -> start ...");
|
||||
// Load in all the "core" schema, that we already have in "memory".
|
||||
let entries = self.schema.to_entries();
|
||||
|
@ -479,320 +568,6 @@ impl QueryServerWriteTransaction<'_> {
|
|||
debug_assert!(r.is_ok());
|
||||
r
|
||||
}
|
||||
|
||||
#[instrument(level = "info", skip_all)]
|
||||
pub fn initialise_schema_idm(&mut self) -> Result<(), OperationError> {
|
||||
admin_debug!("initialise_schema_idm -> start ...");
|
||||
|
||||
// ⚠️ DOMAIN LEVEL 1 SCHEMA ATTRIBUTES ⚠️
|
||||
// Future schema attributes need to be added via migrations.
|
||||
//
|
||||
// DO NOT MODIFY THIS DEFINITION
|
||||
let idm_schema_attrs = [
|
||||
SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(),
|
||||
];
|
||||
|
||||
let r: Result<(), _> = idm_schema_attrs
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry));
|
||||
|
||||
if r.is_err() {
|
||||
error!(res = ?r, "initialise_schema_idm -> Error");
|
||||
}
|
||||
debug_assert!(r.is_ok());
|
||||
|
||||
// ⚠️ DOMAIN LEVEL 1 SCHEMA ATTRIBUTES ⚠️
|
||||
// Future schema classes need to be added via migrations.
|
||||
//
|
||||
// DO NOT MODIFY THIS DEFINITION
|
||||
let idm_schema: Vec<EntryInitNew> = vec![
|
||||
// SCHEMA_ATTR_MAIL.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(),
|
||||
SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(),
|
||||
SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(),
|
||||
SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(),
|
||||
SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(),
|
||||
SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(),
|
||||
// SCHEMA_ATTR_DISPLAYNAME.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_NAME.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_SSID.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_UUID.clone().into(),
|
||||
SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(),
|
||||
SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(),
|
||||
SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(),
|
||||
SCHEMA_ATTR_GIDNUMBER.clone().into(),
|
||||
SCHEMA_ATTR_GRANT_UI_HINT.clone().into(),
|
||||
SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(),
|
||||
// SCHEMA_ATTR_LEGALNAME.clone().into(),
|
||||
SCHEMA_ATTR_LOGINSHELL.clone().into(),
|
||||
SCHEMA_ATTR_NAME_HISTORY.clone().into(),
|
||||
SCHEMA_ATTR_NSUNIQUEID.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
|
||||
.clone()
|
||||
.into(),
|
||||
SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(),
|
||||
// SCHEMA_ATTR_OAUTH2_RS_ORIGIN.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_PASSKEYS.clone().into(),
|
||||
SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(),
|
||||
SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(),
|
||||
SCHEMA_ATTR_RADIUS_SECRET.clone().into(),
|
||||
SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(),
|
||||
SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_COOKIE.clone().into(),
|
||||
SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_UNIX_PASSWORD.clone().into(),
|
||||
SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(),
|
||||
SCHEMA_ATTR_DENIED_NAME.clone().into(),
|
||||
SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(),
|
||||
SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4
|
||||
.clone()
|
||||
.into(),
|
||||
// DL5
|
||||
// DL6
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(),
|
||||
SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(),
|
||||
SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(),
|
||||
// DL7
|
||||
SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(),
|
||||
SCHEMA_ATTR_REFERS_DL7.clone().into(),
|
||||
SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(),
|
||||
SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(),
|
||||
SCHEMA_ATTR_MAIL_DL7.clone().into(),
|
||||
SCHEMA_ATTR_LEGALNAME_DL7.clone().into(),
|
||||
SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(),
|
||||
SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(),
|
||||
SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(),
|
||||
];
|
||||
|
||||
let r = idm_schema
|
||||
.into_iter()
|
||||
// Each item individually logs it's result
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry));
|
||||
|
||||
if r.is_err() {
|
||||
error!(res = ?r, "initialise_schema_idm -> Error");
|
||||
}
|
||||
|
||||
debug_assert!(r.is_ok());
|
||||
|
||||
// ⚠️ DOMAIN LEVEL 1 SCHEMA CLASSES ⚠️
|
||||
// Future schema classes need to be added via migrations.
|
||||
//
|
||||
// DO NOT MODIFY THIS DEFINITION
|
||||
let idm_schema_classes_dl1: Vec<EntryInitNew> = vec![
|
||||
SCHEMA_CLASS_DYNGROUP.clone().into(),
|
||||
SCHEMA_CLASS_ORGPERSON.clone().into(),
|
||||
SCHEMA_CLASS_POSIXACCOUNT.clone().into(),
|
||||
SCHEMA_CLASS_POSIXGROUP.clone().into(),
|
||||
SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(),
|
||||
// DL4
|
||||
SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(),
|
||||
// DL5
|
||||
// SCHEMA_CLASS_PERSON_DL5.clone().into(),
|
||||
SCHEMA_CLASS_ACCOUNT_DL5.clone().into(),
|
||||
// SCHEMA_CLASS_OAUTH2_RS_DL5.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(),
|
||||
// DL6
|
||||
// SCHEMA_CLASS_ACCOUNT_POLICY_DL6.clone().into(),
|
||||
// SCHEMA_CLASS_SERVICE_ACCOUNT_DL6.clone().into(),
|
||||
// SCHEMA_CLASS_SYNC_ACCOUNT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_GROUP_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(),
|
||||
// SCHEMA_CLASS_DOMAIN_INFO_DL6.clone().into(),
|
||||
// DL7
|
||||
// SCHEMA_CLASS_DOMAIN_INFO_DL7.clone().into(),
|
||||
SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(),
|
||||
SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(),
|
||||
SCHEMA_CLASS_OAUTH2_RS_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(),
|
||||
SCHEMA_CLASS_APPLICATION_DL8.clone().into(),
|
||||
SCHEMA_CLASS_PERSON_DL8.clone().into(),
|
||||
SCHEMA_CLASS_DOMAIN_INFO_DL8.clone().into(),
|
||||
];
|
||||
|
||||
let r: Result<(), _> = idm_schema_classes_dl1
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry));
|
||||
|
||||
if r.is_err() {
|
||||
error!(res = ?r, "initialise_schema_idm -> Error");
|
||||
}
|
||||
debug_assert!(r.is_ok());
|
||||
|
||||
debug!("initialise_schema_idm -> Ok!");
|
||||
|
||||
r
|
||||
}
|
||||
|
||||
#[instrument(level = "info", skip_all)]
|
||||
/// This function is idempotent, runs all the startup functionality and checks
|
||||
pub fn initialise_domain_info(&mut self) -> Result<(), OperationError> {
|
||||
// Configure the default key provider. This needs to exist *before* the
|
||||
// domain info!
|
||||
self.internal_migrate_or_create(E_KEY_PROVIDER_INTERNAL_DL6.clone())
|
||||
.and_then(|_| self.reload())
|
||||
.map_err(|err| {
|
||||
error!(?err, "initialise_domain_info::E_KEY_PROVIDER_INTERNAL_DL6");
|
||||
debug_assert!(false);
|
||||
err
|
||||
})?;
|
||||
|
||||
self.internal_migrate_or_create(E_SYSTEM_INFO_V1.clone())
|
||||
.and_then(|_| self.internal_migrate_or_create(E_DOMAIN_INFO_DL6.clone()))
|
||||
.and_then(|_| self.internal_migrate_or_create(E_SYSTEM_CONFIG_V1.clone()))
|
||||
.map_err(|err| {
|
||||
error!(?err, "initialise_domain_info");
|
||||
debug_assert!(false);
|
||||
err
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "info", skip_all)]
|
||||
/// This function is idempotent, runs all the startup functionality and checks
|
||||
pub fn initialise_idm(&mut self) -> Result<(), OperationError> {
|
||||
// The domain info now exists, we should be able to do these migrations as they will
|
||||
// cause SPN regenerations to occur
|
||||
|
||||
// Delete entries that no longer need to exist.
|
||||
// TODO: Shouldn't this be a migration?
|
||||
// Check the admin object exists (migrations).
|
||||
// Create the default idm_admin group.
|
||||
let admin_entries: Vec<EntryInitNew> = idm_builtin_admin_entries()?;
|
||||
let res: Result<(), _> = admin_entries
|
||||
.into_iter()
|
||||
// Each item individually logs it's result
|
||||
.try_for_each(|ent| self.internal_migrate_or_create(ent));
|
||||
if res.is_ok() {
|
||||
debug!("initialise_idm p1 -> result Ok!");
|
||||
} else {
|
||||
error!(?res, "initialise_idm p1 -> result");
|
||||
}
|
||||
debug_assert!(res.is_ok());
|
||||
res?;
|
||||
|
||||
let res: Result<(), _> = idm_builtin_non_admin_groups()
|
||||
.into_iter()
|
||||
.try_for_each(|e| self.internal_migrate_or_create(e.clone().try_into()?));
|
||||
if res.is_ok() {
|
||||
debug!("initialise_idm p2 -> result Ok!");
|
||||
} else {
|
||||
error!(?res, "initialise_idm p2 -> result");
|
||||
}
|
||||
debug_assert!(res.is_ok());
|
||||
res?;
|
||||
|
||||
// ⚠️ DOMAIN LEVEL 1 ENTRIES ⚠️
|
||||
// Future entries need to be added via migrations.
|
||||
//
|
||||
// DO NOT MODIFY THIS DEFINITION
|
||||
let idm_entries: Vec<BuiltinAcp> = vec![
|
||||
// Built in access controls.
|
||||
IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone(),
|
||||
IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone(),
|
||||
IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone(),
|
||||
IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone(),
|
||||
IDM_ACP_ACP_MANAGE_V1.clone(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone(),
|
||||
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone(),
|
||||
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone(),
|
||||
IDM_ACP_RADIUS_SERVERS_V1.clone(),
|
||||
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone(),
|
||||
IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone(),
|
||||
// IDM_ACP_SELF_READ_V1.clone(),
|
||||
// IDM_ACP_SELF_WRITE_V1.clone(),
|
||||
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone(),
|
||||
// IDM_ACP_SELF_NAME_WRITE_V1.clone(),
|
||||
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone(),
|
||||
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1.clone(),
|
||||
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone(),
|
||||
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone(),
|
||||
IDM_ACP_GROUP_READ_V1.clone(),
|
||||
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone(),
|
||||
IDM_ACP_PEOPLE_PII_READ_V1.clone(),
|
||||
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone(),
|
||||
IDM_ACP_PEOPLE_READ_V1.clone(),
|
||||
IDM_ACP_PEOPLE_MANAGE_V1.clone(),
|
||||
IDM_ACP_PEOPLE_DELETE_V1.clone(),
|
||||
IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone(),
|
||||
IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1.clone(),
|
||||
IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1.clone(),
|
||||
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone(),
|
||||
// DL4
|
||||
// DL5
|
||||
// IDM_ACP_OAUTH2_MANAGE_DL5.clone(),
|
||||
// DL6
|
||||
// IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone(),
|
||||
IDM_ACP_PEOPLE_CREATE_DL6.clone(),
|
||||
IDM_ACP_GROUP_MANAGE_DL6.clone(),
|
||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone(),
|
||||
// IDM_ACP_DOMAIN_ADMIN_DL6.clone(),
|
||||
// DL7
|
||||
// IDM_ACP_SELF_WRITE_DL7.clone(),
|
||||
IDM_ACP_SELF_NAME_WRITE_DL7.clone(),
|
||||
IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone(),
|
||||
IDM_ACP_OAUTH2_MANAGE_DL7.clone(),
|
||||
// DL8
|
||||
IDM_ACP_SELF_READ_DL8.clone(),
|
||||
IDM_ACP_SELF_WRITE_DL8.clone(),
|
||||
IDM_ACP_APPLICATION_MANAGE_DL8.clone(),
|
||||
IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone(),
|
||||
IDM_ACP_MAIL_SERVERS_DL8.clone(),
|
||||
IDM_ACP_DOMAIN_ADMIN_DL8.clone(),
|
||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone(),
|
||||
];
|
||||
|
||||
let res: Result<(), _> = idm_entries
|
||||
.into_iter()
|
||||
.try_for_each(|entry| self.internal_migrate_or_create(entry.into()));
|
||||
if res.is_ok() {
|
||||
admin_debug!("initialise_idm p3 -> result Ok!");
|
||||
} else {
|
||||
admin_error!(?res, "initialise_idm p3 -> result");
|
||||
}
|
||||
debug_assert!(res.is_ok());
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryServerReadTransaction<'_> {
|
||||
|
|
|
@ -2420,8 +2420,17 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
debug!(domain_previous_version = ?previous_version, domain_target_version = ?domain_info_version);
|
||||
debug!(domain_previous_patch_level = ?previous_patch_level, domain_target_patch_level = ?domain_info_patch_level);
|
||||
|
||||
// We have to check for DL0 since that's the initialisation level.
|
||||
if previous_version < DOMAIN_MIN_REMIGRATION_LEVEL && previous_version != DOMAIN_LEVEL_0 {
|
||||
// We have to check for DL0 since that's the initialisation level. If we are at DL0 then
|
||||
// the server was just brought up and there are no other actions to take since we are
|
||||
// now at TGT level.
|
||||
if previous_version == DOMAIN_LEVEL_0 {
|
||||
debug!(
|
||||
"Server was just brought up, skipping migrations as we are already at target level"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if previous_version < DOMAIN_MIN_REMIGRATION_LEVEL {
|
||||
error!("UNABLE TO PROCEED. You are attempting a Skip update which is NOT SUPPORTED. You must upgrade one-version of Kanidm at a time.");
|
||||
error!("For more see: https://kanidm.github.io/kanidm/stable/support.html#upgrade-policy and https://kanidm.github.io/kanidm/stable/server_updates.html");
|
||||
error!(domain_previous_version = ?previous_version, domain_target_version = ?domain_info_version);
|
||||
|
@ -2434,7 +2443,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
self.migrate_domain_8_to_9()?;
|
||||
}
|
||||
|
||||
if previous_patch_level < PATCH_LEVEL_2 && domain_info_patch_level >= PATCH_LEVEL_2 {
|
||||
if previous_patch_level < PATCH_LEVEL_2
|
||||
&& domain_info_patch_level >= PATCH_LEVEL_2
|
||||
&& domain_info_version == DOMAIN_LEVEL_9
|
||||
{
|
||||
self.migrate_domain_patch_level_2()?;
|
||||
}
|
||||
|
||||
|
@ -2573,7 +2585,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
fn set_phase(&mut self, phase: ServerPhase) {
|
||||
*self.phase = phase
|
||||
// Phase changes are one way
|
||||
if phase > *self.phase {
|
||||
*self.phase = phase
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_phase(&mut self) -> ServerPhase {
|
||||
|
|
|
@ -615,9 +615,11 @@ mod tests {
|
|||
Err(OperationError::EmptyRequest)
|
||||
);
|
||||
|
||||
let idm_admin = server_txn.internal_search_uuid(UUID_IDM_ADMIN).unwrap();
|
||||
|
||||
// Mod changes no objects
|
||||
let me_nochg = ModifyEvent::new_impersonate_entry_ser(
|
||||
BUILTIN_ACCOUNT_IDM_ADMIN.clone(),
|
||||
let me_nochg = ModifyEvent::new_impersonate_entry(
|
||||
idm_admin,
|
||||
filter!(f_eq(
|
||||
Attribute::Name,
|
||||
PartialValue::new_iname("flarbalgarble")
|
||||
|
|
|
@ -89,7 +89,7 @@ pub async fn setup_idm_test(
|
|||
) -> (IdmServer, IdmServerDelayed, IdmServerAudit) {
|
||||
let qs = setup_test(config).await;
|
||||
|
||||
IdmServer::new(qs, "https://idm.example.com")
|
||||
IdmServer::new(qs, "https://idm.example.com", true)
|
||||
.await
|
||||
.expect("Failed to setup idms")
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ edition = { workspace = true }
|
|||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -14,7 +14,7 @@ repository = { workspace = true }
|
|||
[lib]
|
||||
name = "kanidmd_testkit"
|
||||
path = "src/lib.rs"
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[features]
|
||||
|
@ -25,7 +25,6 @@ webdriver = []
|
|||
dev-oauth2-device-flow = []
|
||||
|
||||
[dependencies]
|
||||
http = { workspace = true }
|
||||
kanidm_client = { workspace = true }
|
||||
kanidm_proto = { workspace = true }
|
||||
kanidmd_core = { workspace = true }
|
||||
|
@ -57,7 +56,6 @@ futures = { workspace = true }
|
|||
oauth2_ext = { workspace = true, default-features = false, features = [
|
||||
"reqwest",
|
||||
] }
|
||||
openssl = { workspace = true }
|
||||
petgraph = { version = "0.7.1", features = ["serde"] }
|
||||
serde_json = { workspace = true }
|
||||
time = { workspace = true }
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
//!
|
||||
|
||||
use kanidmd_lib::constants::entries::Attribute;
|
||||
use kanidmd_lib::constants::groups::{idm_builtin_admin_groups, idm_builtin_non_admin_groups};
|
||||
use kanidmd_lib::migration_data::current::{
|
||||
phase_5_builtin_admin_entries, phase_6_builtin_non_admin_entries
|
||||
};
|
||||
use kanidmd_lib::prelude::{builtin_accounts, EntryInitNew};
|
||||
use petgraph::graphmap::{AllEdges, GraphMap, NodeTrait};
|
||||
use petgraph::Directed;
|
||||
|
@ -106,8 +108,8 @@ async fn enumerate_default_groups(/*_client: KanidmClient*/) {
|
|||
graph.add_node(account.uuid);
|
||||
});
|
||||
|
||||
let mut groups = idm_builtin_admin_groups();
|
||||
groups.extend(idm_builtin_non_admin_groups());
|
||||
let mut groups = phase_5_builtin_admin_entries();
|
||||
groups.extend(phase_6_builtin_non_admin_entries());
|
||||
|
||||
groups.into_iter().for_each(|group| {
|
||||
uuidmap.insert(group.uuid, group.clone().try_into().unwrap());
|
|
@ -12,10 +12,9 @@ use kanidm_proto::oauth2::{
|
|||
AccessTokenRequest, AccessTokenResponse, AuthorisationResponse, GrantTypeReq,
|
||||
};
|
||||
|
||||
use kanidmd_lib::constants::NAME_IDM_ALL_ACCOUNTS;
|
||||
use kanidmd_lib::prelude::uri::{OAUTH2_AUTHORISE_DEVICE, OAUTH2_TOKEN_ENDPOINT};
|
||||
use kanidmd_lib::prelude::{
|
||||
Attribute, IDM_ALL_ACCOUNTS, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID, OAUTH2_SCOPE_READ,
|
||||
};
|
||||
use kanidmd_lib::prelude::{Attribute, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID, OAUTH2_SCOPE_READ};
|
||||
use kanidmd_testkit::{
|
||||
assert_no_cache, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER, IDM_ADMIN_TEST_PASSWORD,
|
||||
IDM_ADMIN_TEST_USER, NOT_ADMIN_TEST_EMAIL, NOT_ADMIN_TEST_PASSWORD, NOT_ADMIN_TEST_USERNAME,
|
||||
|
@ -159,7 +158,7 @@ async fn oauth2_device_flow(rsclient: KanidmClient) {
|
|||
rsclient
|
||||
.idm_oauth2_rs_update_scope_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
vec![OAUTH2_SCOPE_READ, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID],
|
||||
)
|
||||
.await
|
||||
|
@ -168,7 +167,7 @@ async fn oauth2_device_flow(rsclient: KanidmClient) {
|
|||
rsclient
|
||||
.idm_oauth2_rs_update_sup_scope_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
vec![ADMIN_TEST_USER],
|
||||
)
|
||||
.await
|
||||
|
@ -179,7 +178,7 @@ async fn oauth2_device_flow(rsclient: KanidmClient) {
|
|||
.idm_oauth2_rs_update_claim_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
"test_claim",
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
&["claim_a".to_string(), "claim_b".to_string()],
|
||||
)
|
||||
.await
|
|
@ -18,7 +18,7 @@ use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
|||
use kanidm_proto::internal::{Filter, Modify, ModifyList};
|
||||
use kanidmd_core::config::{Configuration, IntegrationTestConfig};
|
||||
use kanidmd_core::{create_server_core, CoreHandle};
|
||||
use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1};
|
||||
use kanidmd_lib::prelude::{Attribute, NAME_SYSTEM_ADMINS};
|
||||
use tokio::task;
|
||||
|
||||
pub const ADMIN_TEST_USER: &str = "admin";
|
||||
|
@ -92,6 +92,7 @@ pub async fn setup_async_test(mut config: Configuration) -> (KanidmClient, CoreH
|
|||
#[allow(clippy::panic)]
|
||||
let rsclient = match KanidmClientBuilder::new()
|
||||
.address(addr.clone())
|
||||
.enable_native_ca_roots(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
{
|
||||
|
@ -385,7 +386,7 @@ pub async fn login_put_admin_idm_admins(rsclient: &KanidmClient) {
|
|||
|
||||
#[allow(clippy::expect_used)]
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &[ADMIN_TEST_USER])
|
||||
.idm_group_add_members(NAME_SYSTEM_ADMINS, &[ADMIN_TEST_USER])
|
||||
.await
|
||||
.expect("Failed to add admin user to idm_admins")
|
||||
}
|
||||
|
@ -396,7 +397,7 @@ macro_rules! assert_no_cache {
|
|||
// Check we have correct nocache headers.
|
||||
let cache_header: &str = $response
|
||||
.headers()
|
||||
.get(http::header::CACHE_CONTROL)
|
||||
.get(kanidm_client::http::header::CACHE_CONTROL)
|
||||
.expect("missing cache-control header")
|
||||
.to_str()
|
||||
.expect("invalid cache-control header");
|
||||
|
|
11
server/testkit/tests/DO_NOT_ADD_MORE_TESTS_HERE
Normal file
11
server/testkit/tests/DO_NOT_ADD_MORE_TESTS_HERE
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
DO NOT ADD MORE TESTS TO THIS DIRECTORY
|
||||
|
||||
Add them to the `testkit` directory.
|
||||
|
||||
Each new test in this folder is a separate binary, that must be complied linked and executed. This
|
||||
takes HUGES AMOUNTS OF TIME. It makes tests unbelievably slow.
|
||||
|
||||
If you want to add an integration test, put it into the testkit dir so it becomes part of the
|
||||
single larger integration test runner.
|
||||
|
3
server/testkit/tests/integration_test.rs
Normal file
3
server/testkit/tests/integration_test.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
mod testkit;
|
|
@ -1,57 +0,0 @@
|
|||
use kanidm_client::KanidmClient;
|
||||
|
||||
/// This literally tests that the thing exists and responds in a way we expect, probably worth testing it better...
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_v1_self_applinks(rsclient: KanidmClient) {
|
||||
// We need to do manual reqwests here.
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let response = match client
|
||||
.get(rsclient.make_url("/v1/self/_applinks"))
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!(
|
||||
"Failed to query {:?} : {:#?}",
|
||||
rsclient.make_url("/v1/self/_applinks"),
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
eprintln!("response: {:#?}", response);
|
||||
assert_eq!(response.status(), 401);
|
||||
|
||||
let body = response.text().await.unwrap();
|
||||
eprintln!("{}", body);
|
||||
}
|
||||
|
||||
/// This literally tests that the thing exists and responds in a way we expect, probably worth testing it better...
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_v1_self_whoami_uat(rsclient: KanidmClient) {
|
||||
// We need to do manual reqwests here.
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let response = match client.get(rsclient.make_url("/v1/self/_uat")).send().await {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!(
|
||||
"Failed to query {:?} : {:#?}",
|
||||
rsclient.make_url("/v1/self/_uat"),
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
eprintln!("response: {:#?}", response);
|
||||
assert_eq!(response.status(), 401);
|
||||
|
||||
let body = response.text().await.unwrap();
|
||||
eprintln!("{}", body);
|
||||
}
|
|
@ -12,21 +12,18 @@ async fn check_that_the_swagger_api_loads(rsclient: kanidm_client::KanidmClient)
|
|||
rsclient.set_token("".into()).await;
|
||||
info!("Running test: check_that_the_swagger_api_loads");
|
||||
let url = rsclient.make_url("/docs/v1/openapi.json");
|
||||
let openapi_response: OpenAPIResponse = reqwest::get(url.clone())
|
||||
|
||||
let openapi_response = rsclient
|
||||
.perform_get_request::<OpenAPIResponse>(url.as_str())
|
||||
.await
|
||||
.expect("Failed to get openapi.json")
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
.expect("Failed to get openapi.json");
|
||||
assert_eq!(openapi_response.openapi, "3.0.3");
|
||||
|
||||
// this validates that it's valid JSON schema, but not that it's valid openapi... but it's a start.
|
||||
let schema: serde_json::Value = reqwest::get(url)
|
||||
let schema = rsclient
|
||||
.perform_get_request::<serde_json::Value>(url.as_str())
|
||||
.await
|
||||
.expect("Failed to get openapi.json")
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
.expect("Failed to get openapi.json");
|
||||
|
||||
let instance = serde_json::json!("foo");
|
||||
let compiled = Validator::new(&schema).expect("A valid schema");
|
|
@ -1,4 +1,4 @@
|
|||
use kanidm_client::{ClientError, KanidmClient};
|
||||
use kanidm_client::{ClientError, KanidmClient, StatusCode};
|
||||
use kanidm_proto::constants::ATTR_DESCRIPTION;
|
||||
use kanidmd_testkit::{create_user, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER};
|
||||
use serde_json::Value;
|
||||
|
@ -48,6 +48,6 @@ async fn test_v1_group_id_attr_post(rsclient: KanidmClient) {
|
|||
eprintln!("response: {:#?}", response);
|
||||
assert!(matches!(
|
||||
response,
|
||||
ClientError::Http(reqwest::StatusCode::BAD_REQUEST, _, _)
|
||||
ClientError::Http(StatusCode::BAD_REQUEST, _, _)
|
||||
));
|
||||
}
|
|
@ -1,11 +1,16 @@
|
|||
use kanidm_client::KanidmClient;
|
||||
use kanidm_client::{http::header, KanidmClient};
|
||||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_https_manifest(rsclient: KanidmClient) {
|
||||
// We need to do manual reqwests here.
|
||||
let client = rsclient.client();
|
||||
|
||||
// here we test the /ui/ endpoint which should have the headers
|
||||
let response = match reqwest::get(rsclient.make_url("/manifest.webmanifest")).await {
|
||||
let response = match client
|
||||
.get(rsclient.make_url("/manifest.webmanifest"))
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!(
|
||||
|
@ -20,8 +25,6 @@ async fn test_https_manifest(rsclient: KanidmClient) {
|
|||
|
||||
eprintln!(
|
||||
"csp headers: {:#?}",
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY)
|
||||
response.headers().get(header::CONTENT_SECURITY_POLICY)
|
||||
);
|
||||
}
|
|
@ -12,10 +12,8 @@ const DEFAULT_IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
|
|||
|
||||
#[kanidmd_testkit::test(trust_x_forward_for = false)]
|
||||
async fn dont_trust_xff_send_header(rsclient: KanidmClient) {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(
|
||||
|
@ -35,10 +33,8 @@ async fn dont_trust_xff_send_header(rsclient: KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test(trust_x_forward_for = false)]
|
||||
async fn dont_trust_xff_dont_send_header(rsclient: KanidmClient) {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(
|
||||
|
@ -63,10 +59,8 @@ async fn dont_trust_xff_dont_send_header(rsclient: KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test(trust_x_forward_for = true)]
|
||||
async fn trust_xff_send_invalid_header_single_value(rsclient: KanidmClient) {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(
|
||||
|
@ -85,10 +79,8 @@ async fn trust_xff_send_invalid_header_single_value(rsclient: KanidmClient) {
|
|||
//
|
||||
#[kanidmd_testkit::test(trust_x_forward_for = true)]
|
||||
async fn trust_xff_send_invalid_header_multiple_values(rsclient: KanidmClient) {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(
|
||||
|
@ -106,10 +98,8 @@ async fn trust_xff_send_invalid_header_multiple_values(rsclient: KanidmClient) {
|
|||
async fn trust_xff_send_valid_header_single_ipv4_address(rsclient: KanidmClient) {
|
||||
let ip_addr = "2001:db8:85a3:8d3:1319:8a2e:370:7348";
|
||||
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(X_FORWARDED_FOR, ip_addr)
|
||||
|
@ -128,10 +118,8 @@ async fn trust_xff_send_valid_header_single_ipv4_address(rsclient: KanidmClient)
|
|||
async fn trust_xff_send_valid_header_single_ipv6_address(rsclient: KanidmClient) {
|
||||
let ip_addr = "203.0.113.195";
|
||||
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(X_FORWARDED_FOR, ip_addr)
|
||||
|
@ -150,10 +138,8 @@ async fn trust_xff_send_valid_header_single_ipv6_address(rsclient: KanidmClient)
|
|||
async fn trust_xff_send_valid_header_multiple_address(rsclient: KanidmClient) {
|
||||
let first_ip_addr = "203.0.113.195, 2001:db8:85a3:8d3:1319:8a2e:370:7348";
|
||||
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(X_FORWARDED_FOR, first_ip_addr)
|
||||
|
@ -172,10 +158,6 @@ async fn trust_xff_send_valid_header_multiple_address(rsclient: KanidmClient) {
|
|||
|
||||
let second_ip_addr = "2001:db8:85a3:8d3:1319:8a2e:370:7348, 198.51.100.178, 203.0.113.195";
|
||||
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.header(X_FORWARDED_FOR, second_ip_addr)
|
||||
|
@ -195,10 +177,8 @@ async fn trust_xff_send_valid_header_multiple_address(rsclient: KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test(trust_x_forward_for = true)]
|
||||
async fn trust_xff_dont_send_header(rsclient: KanidmClient) {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let res = client
|
||||
.get(rsclient.make_url("/v1/debug/ipinfo"))
|
||||
.send()
|
|
@ -1,11 +1,13 @@
|
|||
use kanidm_client::http::header;
|
||||
use kanidm_client::KanidmClient;
|
||||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_https_middleware_headers(rsclient: KanidmClient) {
|
||||
// We need to do manual reqwests here.
|
||||
let client = rsclient.client();
|
||||
|
||||
// here we test the /ui/ endpoint which should have the headers
|
||||
let response = match reqwest::get(rsclient.make_url("/ui")).await {
|
||||
let response = match client.get(rsclient.make_url("/ui")).send().await {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!(
|
||||
|
@ -19,19 +21,15 @@ async fn test_https_middleware_headers(rsclient: KanidmClient) {
|
|||
assert_eq!(response.status(), 200);
|
||||
eprintln!(
|
||||
"csp headers: {:#?}",
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY)
|
||||
response.headers().get(header::CONTENT_SECURITY_POLICY)
|
||||
);
|
||||
assert_ne!(
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY),
|
||||
response.headers().get(header::CONTENT_SECURITY_POLICY),
|
||||
None
|
||||
);
|
||||
|
||||
// here we test the /ui/login endpoint which should have the headers
|
||||
let response = match reqwest::get(rsclient.make_url("/ui/login")).await {
|
||||
let response = match client.get(rsclient.make_url("/ui/login")).send().await {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!(
|
||||
|
@ -46,14 +44,10 @@ async fn test_https_middleware_headers(rsclient: KanidmClient) {
|
|||
|
||||
eprintln!(
|
||||
"csp headers: {:#?}",
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY)
|
||||
response.headers().get(header::CONTENT_SECURITY_POLICY)
|
||||
);
|
||||
assert_ne!(
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY),
|
||||
response.headers().get(header::CONTENT_SECURITY_POLICY),
|
||||
None
|
||||
);
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
use core::result::Result::Err;
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_client::{KanidmClient, StatusCode};
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use kanidm_proto::internal::{IdentifyUserRequest, IdentifyUserResponse};
|
||||
|
||||
use kanidmd_lib::prelude::Attribute;
|
||||
use kanidmd_testkit::ADMIN_TEST_PASSWORD;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
static UNIVERSAL_PW: &str = "eicieY7ahchaoCh0eeTa";
|
||||
|
||||
|
@ -26,14 +24,14 @@ async fn test_not_authenticated(rsclient: KanidmClient) {
|
|||
.idm_person_identify_user(USER_A_NAME, IdentifyUserRequest::Start)
|
||||
.await;
|
||||
assert!(
|
||||
matches!(res, Err(err) if matches!(err, kanidm_client::ClientError::Http(reqwest::StatusCode::UNAUTHORIZED, ..)))
|
||||
matches!(res, Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::UNAUTHORIZED, ..)))
|
||||
);
|
||||
|
||||
let res = rsclient
|
||||
.idm_person_identify_user(USER_A_NAME, IdentifyUserRequest::DisplayCode)
|
||||
.await;
|
||||
assert!(
|
||||
matches!(res, Err(err) if matches!(err, kanidm_client::ClientError::Http(reqwest::StatusCode::UNAUTHORIZED, ..)))
|
||||
matches!(res, Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::UNAUTHORIZED, ..)))
|
||||
);
|
||||
let res = rsclient
|
||||
.idm_person_identify_user(
|
||||
|
@ -43,7 +41,7 @@ async fn test_not_authenticated(rsclient: KanidmClient) {
|
|||
.await;
|
||||
|
||||
assert!(
|
||||
matches!(res, Err(err) if matches!(err, kanidm_client::ClientError::Http(reqwest::StatusCode::UNAUTHORIZED, ..)))
|
||||
matches!(res, Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::UNAUTHORIZED, ..)))
|
||||
);
|
||||
}
|
||||
|
16
server/testkit/tests/testkit/mod.rs
Normal file
16
server/testkit/tests/testkit/mod.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
mod apidocs;
|
||||
mod domain;
|
||||
mod group;
|
||||
mod http_manifest;
|
||||
mod https_extractors;
|
||||
mod https_middleware;
|
||||
mod identity_verification_tests;
|
||||
mod integration;
|
||||
mod mtls_test;
|
||||
mod oauth2_test;
|
||||
mod person;
|
||||
mod proto_v1_test;
|
||||
mod scim_test;
|
||||
mod service_account;
|
||||
mod system;
|
||||
mod unix;
|
|
@ -12,14 +12,14 @@ use kanidm_proto::oauth2::{
|
|||
AccessTokenResponse, AccessTokenType, AuthorisationResponse, GrantTypeReq,
|
||||
OidcDiscoveryResponse,
|
||||
};
|
||||
use kanidmd_lib::prelude::{Attribute, IDM_ALL_ACCOUNTS};
|
||||
use kanidmd_lib::constants::NAME_IDM_ALL_ACCOUNTS;
|
||||
use kanidmd_lib::prelude::Attribute;
|
||||
use oauth2_ext::PkceCodeChallenge;
|
||||
use reqwest::header::{HeaderValue, CONTENT_TYPE};
|
||||
use reqwest::StatusCode;
|
||||
use uri::{OAUTH2_TOKEN_ENDPOINT, OAUTH2_TOKEN_INTROSPECT_ENDPOINT, OAUTH2_TOKEN_REVOKE_ENDPOINT};
|
||||
use url::{form_urlencoded::parse as query_parse, Url};
|
||||
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_client::{http::header, KanidmClient, StatusCode};
|
||||
use kanidmd_testkit::{
|
||||
assert_no_cache, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER, NOT_ADMIN_TEST_EMAIL,
|
||||
NOT_ADMIN_TEST_PASSWORD, NOT_ADMIN_TEST_USERNAME, TEST_INTEGRATION_RS_DISPLAY,
|
||||
|
@ -98,7 +98,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
rsclient
|
||||
.idm_oauth2_rs_update_scope_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
vec![OAUTH2_SCOPE_READ, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID],
|
||||
)
|
||||
.await
|
||||
|
@ -107,7 +107,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
rsclient
|
||||
.idm_oauth2_rs_update_sup_scope_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
vec![ADMIN_TEST_USER],
|
||||
)
|
||||
.await
|
||||
|
@ -136,6 +136,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
// from here, we can now begin what would be a "interaction" to the oauth server.
|
||||
// Create a new reqwest client - we'll be using this manually.
|
||||
let client = reqwest::Client::builder()
|
||||
.tls_built_in_native_certs(false)
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.no_proxy()
|
||||
.build()
|
||||
|
@ -151,11 +152,11 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send discovery preflight request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let cors_header: &str = response
|
||||
.headers()
|
||||
.get(http::header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.expect("missing access-control-allow-origin header")
|
||||
.to_str()
|
||||
.expect("invalid access-control-allow-origin header");
|
||||
|
@ -167,12 +168,12 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Assert CORS on the GET too.
|
||||
let cors_header: &str = response
|
||||
.headers()
|
||||
.get(http::header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.expect("missing access-control-allow-origin header")
|
||||
.to_str()
|
||||
.expect("invalid access-control-allow-origin header");
|
||||
|
@ -220,7 +221,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_no_cache!(response);
|
||||
|
||||
let mut jwk_set: JwkKeySet = response
|
||||
|
@ -263,7 +264,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_no_cache!(response);
|
||||
|
||||
let consent_req: AuthorisationResponse = response
|
||||
|
@ -297,7 +298,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.expect("Failed to send request.");
|
||||
|
||||
// This should yield a 302 redirect with some query params.
|
||||
assert_eq!(response.status(), reqwest::StatusCode::FOUND);
|
||||
assert_eq!(response.status(), StatusCode::FOUND);
|
||||
assert_no_cache!(response);
|
||||
|
||||
// And we should have a URL in the location header.
|
||||
|
@ -342,11 +343,11 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send code exchange request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let cors_header: &str = response
|
||||
.headers()
|
||||
.get(http::header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.expect("missing access-control-allow-origin header")
|
||||
.to_str()
|
||||
.expect("invalid access-control-allow-origin header");
|
||||
|
@ -378,7 +379,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send token introspect request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
tracing::trace!("{:?}", response.headers());
|
||||
assert!(
|
||||
response.headers().get(CONTENT_TYPE) == Some(&HeaderValue::from_static(APPLICATION_JSON))
|
||||
|
@ -484,7 +485,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send client credentials request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let atr = response
|
||||
.json::<AccessTokenResponse>()
|
||||
|
@ -505,7 +506,7 @@ async fn test_oauth2_openid_basic_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send token introspect request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let tir = response
|
||||
.json::<AccessTokenIntrospectResponse>()
|
||||
|
@ -627,7 +628,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
rsclient
|
||||
.idm_oauth2_rs_update_scope_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
vec![OAUTH2_SCOPE_READ, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID],
|
||||
)
|
||||
.await
|
||||
|
@ -636,7 +637,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
rsclient
|
||||
.idm_oauth2_rs_update_sup_scope_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
vec![ADMIN_TEST_USER],
|
||||
)
|
||||
.await
|
||||
|
@ -647,7 +648,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
.idm_oauth2_rs_update_claim_map(
|
||||
TEST_INTEGRATION_RS_ID,
|
||||
"test_claim",
|
||||
IDM_ALL_ACCOUNTS.name,
|
||||
NAME_IDM_ALL_ACCOUNTS,
|
||||
&["claim_a".to_string(), "claim_b".to_string()],
|
||||
)
|
||||
.await
|
||||
|
@ -680,6 +681,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
// Create a new reqwest client - we'll be using this manually.
|
||||
let client = reqwest::Client::builder()
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.tls_built_in_native_certs(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.expect("Failed to create client.");
|
||||
|
@ -691,7 +693,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_no_cache!(response);
|
||||
|
||||
let mut jwk_set: JwkKeySet = response
|
||||
|
@ -732,7 +734,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_no_cache!(response);
|
||||
|
||||
let consent_req: AuthorisationResponse = response
|
||||
|
@ -764,7 +766,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
.expect("Failed to send request.");
|
||||
|
||||
// This should yield a 302 redirect with some query params.
|
||||
assert_eq!(response.status(), reqwest::StatusCode::FOUND);
|
||||
assert_eq!(response.status(), StatusCode::FOUND);
|
||||
assert_no_cache!(response);
|
||||
|
||||
// And we should have a URL in the location header.
|
||||
|
@ -812,7 +814,7 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send code exchange request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_no_cache!(response);
|
||||
|
||||
// The body is a json AccessTokenResponse
|
||||
|
@ -857,10 +859,10 @@ async fn test_oauth2_openid_public_flow_impl(
|
|||
.await
|
||||
.expect("Failed to send userinfo preflight request.");
|
||||
|
||||
assert_eq!(response.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let cors_header: &str = response
|
||||
.headers()
|
||||
.get(http::header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.expect("missing access-control-allow-origin header")
|
||||
.to_str()
|
||||
.expect("invalid access-control-allow-origin header");
|
||||
|
@ -930,6 +932,7 @@ async fn test_oauth2_token_post_bad_bodies(rsclient: KanidmClient) {
|
|||
|
||||
let client = reqwest::Client::builder()
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.tls_built_in_native_certs(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.expect("Failed to create client.");
|
||||
|
@ -965,6 +968,7 @@ async fn test_oauth2_token_revoke_post(rsclient: KanidmClient) {
|
|||
|
||||
let client = reqwest::Client::builder()
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.tls_built_in_native_certs(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.expect("Failed to create client.");
|
|
@ -1,4 +1,4 @@
|
|||
use kanidm_client::{ClientError, KanidmClient};
|
||||
use kanidm_client::{ClientError, KanidmClient, StatusCode};
|
||||
use kanidm_proto::constants::ATTR_MAIL;
|
||||
use kanidmd_testkit::{create_user, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER};
|
||||
use serde_json::Value;
|
||||
|
@ -48,6 +48,6 @@ async fn test_v1_person_id_ssh_pubkeys_post(rsclient: KanidmClient) {
|
|||
eprintln!("response: {:#?}", response);
|
||||
assert!(matches!(
|
||||
response,
|
||||
ClientError::Http(reqwest::StatusCode::BAD_REQUEST, _, _)
|
||||
ClientError::Http(StatusCode::BAD_REQUEST, _, _)
|
||||
));
|
||||
}
|
|
@ -3,6 +3,7 @@ use std::path::Path;
|
|||
use std::time::SystemTime;
|
||||
|
||||
use kanidm_proto::constants::{ATTR_GIDNUMBER, KSESSIONID};
|
||||
|
||||
use kanidm_proto::internal::{
|
||||
ApiToken, CURegState, Filter, ImageValue, Modify, ModifyList, UatPurpose, UserAuthToken,
|
||||
};
|
||||
|
@ -10,10 +11,10 @@ use kanidm_proto::v1::{
|
|||
AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthResponse, AuthState, AuthStep,
|
||||
Entry,
|
||||
};
|
||||
use kanidmd_lib::constants::{NAME_IDM_ADMINS, NAME_SYSTEM_ADMINS};
|
||||
use kanidmd_lib::credential::totp::Totp;
|
||||
use kanidmd_lib::prelude::{
|
||||
Attribute, BUILTIN_GROUP_IDM_ADMINS_V1, BUILTIN_GROUP_SYSTEM_ADMINS_V1,
|
||||
};
|
||||
|
||||
use kanidmd_lib::prelude::Attribute;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use std::str::FromStr;
|
||||
|
@ -144,10 +145,7 @@ async fn test_server_rest_group_read(rsclient: KanidmClient) {
|
|||
let g_list = rsclient.idm_group_list().await.unwrap();
|
||||
assert!(!g_list.is_empty());
|
||||
|
||||
let g = rsclient
|
||||
.idm_group_get(BUILTIN_GROUP_IDM_ADMINS_V1.name)
|
||||
.await
|
||||
.unwrap();
|
||||
let g = rsclient.idm_group_get(NAME_IDM_ADMINS).await.unwrap();
|
||||
assert!(g.is_some());
|
||||
println!("{:?}", g);
|
||||
}
|
||||
|
@ -165,7 +163,7 @@ async fn test_server_rest_group_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// Create a new group
|
||||
rsclient
|
||||
.idm_group_create("demo_group", Some(BUILTIN_GROUP_IDM_ADMINS_V1.name))
|
||||
.idm_group_create("demo_group", Some(NAME_IDM_ADMINS))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -245,16 +243,13 @@ async fn test_server_rest_group_lifecycle(rsclient: KanidmClient) {
|
|||
assert_eq!(g_list_3.len(), g_list.len());
|
||||
|
||||
// Check we can get an exact group
|
||||
let g = rsclient
|
||||
.idm_group_get(BUILTIN_GROUP_IDM_ADMINS_V1.name)
|
||||
.await
|
||||
.unwrap();
|
||||
let g = rsclient.idm_group_get(NAME_IDM_ADMINS).await.unwrap();
|
||||
assert!(g.is_some());
|
||||
println!("{:?}", g);
|
||||
|
||||
// They should have members
|
||||
let members = rsclient
|
||||
.idm_group_get_members(BUILTIN_GROUP_IDM_ADMINS_V1.name)
|
||||
.idm_group_get_members(NAME_IDM_ADMINS)
|
||||
.await
|
||||
.unwrap();
|
||||
println!("{:?}", members);
|
||||
|
@ -326,7 +321,7 @@ async fn test_server_radius_credential_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// All admin to create persons.
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -397,7 +392,7 @@ async fn test_server_rest_person_account_lifecycle(rsclient: KanidmClient) {
|
|||
// To enable the admin to actually make some of these changes, we have
|
||||
// to make them a people admin. NOT recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -551,7 +546,7 @@ async fn test_server_rest_posix_lifecycle(rsclient: KanidmClient) {
|
|||
assert!(res.is_ok());
|
||||
// Not recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -571,7 +566,7 @@ async fn test_server_rest_posix_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// Extend the group with posix attrs
|
||||
rsclient
|
||||
.idm_group_create("posix_group", Some(BUILTIN_GROUP_IDM_ADMINS_V1.name))
|
||||
.idm_group_create("posix_group", Some(NAME_IDM_ADMINS))
|
||||
.await
|
||||
.unwrap();
|
||||
rsclient
|
||||
|
@ -676,7 +671,7 @@ async fn test_server_rest_posix_auth_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// Not recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -773,7 +768,7 @@ async fn test_server_rest_recycle_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// Not recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -826,7 +821,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) {
|
|||
assert!(res.is_ok());
|
||||
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -902,11 +897,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// Check that we can add scope maps and delete them.
|
||||
rsclient
|
||||
.idm_oauth2_rs_update_scope_map(
|
||||
"test_integration",
|
||||
BUILTIN_GROUP_SYSTEM_ADMINS_V1.name,
|
||||
vec!["a", "b"],
|
||||
)
|
||||
.idm_oauth2_rs_update_scope_map("test_integration", NAME_SYSTEM_ADMINS, vec!["a", "b"])
|
||||
.await
|
||||
.expect("Failed to create scope map");
|
||||
|
||||
|
@ -921,11 +912,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
// Check we can update a scope map
|
||||
rsclient
|
||||
.idm_oauth2_rs_update_scope_map(
|
||||
"test_integration",
|
||||
BUILTIN_GROUP_SYSTEM_ADMINS_V1.name,
|
||||
vec!["a", "b", "c"],
|
||||
)
|
||||
.idm_oauth2_rs_update_scope_map("test_integration", NAME_SYSTEM_ADMINS, vec!["a", "b", "c"])
|
||||
.await
|
||||
.expect("Failed to create scope map");
|
||||
|
||||
|
@ -955,9 +942,8 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) {
|
|||
assert!(res.is_ok());
|
||||
|
||||
//test getting the image
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
let response = client
|
||||
let response = rsclient
|
||||
.client()
|
||||
.get(rsclient.make_url("/ui/images/oauth2/test_integration"))
|
||||
.bearer_auth(rsclient.get_token().await.unwrap());
|
||||
|
||||
|
@ -1009,7 +995,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) {
|
|||
// Check we can delete a scope map.
|
||||
|
||||
rsclient
|
||||
.idm_oauth2_rs_delete_scope_map("test_integration", BUILTIN_GROUP_SYSTEM_ADMINS_V1.name)
|
||||
.idm_oauth2_rs_delete_scope_map("test_integration", NAME_SYSTEM_ADMINS)
|
||||
.await
|
||||
.expect("Failed to delete scope map");
|
||||
|
||||
|
@ -1049,7 +1035,7 @@ async fn test_server_credential_update_session_pw(rsclient: KanidmClient) {
|
|||
|
||||
// Not recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -1124,7 +1110,7 @@ async fn test_server_credential_update_session_totp_pw(rsclient: KanidmClient) {
|
|||
|
||||
// Not recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -1253,7 +1239,7 @@ async fn setup_demo_account_passkey(rsclient: &KanidmClient) -> WebauthnAuthenti
|
|||
|
||||
// Not recommended in production!
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -1409,7 +1395,7 @@ async fn test_server_api_token_lifecycle(rsclient: KanidmClient) {
|
|||
.idm_service_account_create(
|
||||
test_service_account_username,
|
||||
"Test Service",
|
||||
BUILTIN_GROUP_IDM_ADMINS_V1.name,
|
||||
NAME_IDM_ADMINS,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create service account");
|
||||
|
@ -1793,7 +1779,8 @@ async fn start_password_session(
|
|||
password: &str,
|
||||
privileged: bool,
|
||||
) -> Result<UserAuthToken, ()> {
|
||||
let client = reqwest::Client::new();
|
||||
let fresh_rsclient = rsclient.new_session().unwrap();
|
||||
let client = fresh_rsclient.client();
|
||||
|
||||
let authreq = AuthRequest {
|
||||
step: AuthStep::Init2 {
|
|
@ -2,9 +2,9 @@ use compact_jwt::{traits::JwsVerifiable, JwsCompact, JwsEs256Verifier, JwsVerifi
|
|||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::internal::ScimSyncToken;
|
||||
use kanidm_proto::scim_v1::ScimEntryGetQuery;
|
||||
use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1};
|
||||
use kanidmd_lib::constants::NAME_IDM_ADMINS;
|
||||
use kanidmd_lib::prelude::Attribute;
|
||||
use kanidmd_testkit::{ADMIN_TEST_PASSWORD, ADMIN_TEST_USER};
|
||||
use reqwest::header::HeaderValue;
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
|
||||
|
@ -103,64 +103,6 @@ async fn test_sync_account_lifecycle(rsclient: KanidmClient) {
|
|||
.expect("Failed to destroy token");
|
||||
}
|
||||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_scim_sync_get(rsclient: KanidmClient) {
|
||||
// We need to do manual reqwests here.
|
||||
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
headers.insert(
|
||||
reqwest::header::AUTHORIZATION,
|
||||
HeaderValue::from_str(&format!("Bearer {:?}", rsclient.get_token().await)).unwrap(),
|
||||
);
|
||||
|
||||
let client = reqwest::Client::builder()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// here we test the /ui/ endpoint which should have the headers
|
||||
let response = match client.get(rsclient.make_url("/scim/v1/Sync")).send().await {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!(
|
||||
"Failed to query {:?} : {:#?}",
|
||||
rsclient.make_url("/scim/v1/Sync"),
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
eprintln!("response: {:#?}", response);
|
||||
assert!(response.status().is_client_error());
|
||||
|
||||
// check that the CSP headers are coming back
|
||||
eprintln!(
|
||||
"csp headers: {:#?}",
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY)
|
||||
);
|
||||
assert_ne!(
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_SECURITY_POLICY),
|
||||
None
|
||||
);
|
||||
|
||||
// test that the proper content type comes back
|
||||
let url = rsclient.make_url("/scim/v1/Sink");
|
||||
let response = match client.get(url.clone()).send().await {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
panic!("Failed to query {:?} : {:#?}", url, error);
|
||||
}
|
||||
};
|
||||
assert!(response.status().is_success());
|
||||
let content_type = response.headers().get(http::header::CONTENT_TYPE).unwrap();
|
||||
assert!(content_type.to_str().unwrap().contains("text/html"));
|
||||
assert!(response.text().await.unwrap().contains("Sink"));
|
||||
}
|
||||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_scim_sync_entry_get(rsclient: KanidmClient) {
|
||||
let res = rsclient
|
||||
|
@ -170,7 +112,7 @@ async fn test_scim_sync_entry_get(rsclient: KanidmClient) {
|
|||
|
||||
// All admin to create persons.
|
||||
rsclient
|
||||
.idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"])
|
||||
.idm_group_add_members(NAME_IDM_ADMINS, &["admin"])
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
@ -4,10 +4,7 @@ use kanidm_client::KanidmClient;
|
|||
#[kanidmd_testkit::test]
|
||||
async fn test_v1_service_account_id_attr_attr_delete(rsclient: KanidmClient) {
|
||||
// We need to do manual reqwests here.
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
// let post_body = serde_json::json!({"filter": "self"}).to_string();
|
||||
|
|
@ -3,10 +3,7 @@ use kanidm_client::KanidmClient;
|
|||
/// This literally tests that the thing exists and responds in a way we expect, probably worth testing it better...
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_v1_system_post_attr(rsclient: KanidmClient) {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = rsclient.client();
|
||||
|
||||
let response = match client
|
||||
.post(rsclient.make_url("/v1/system/_attr/domain_name"))
|
|
@ -1,5 +1,5 @@
|
|||
use kanidm_client::KanidmClient;
|
||||
use kanidmd_lib::prelude::BUILTIN_GROUP_IDM_ADMINS_V1;
|
||||
use kanidmd_lib::constants::NAME_IDM_ADMINS;
|
||||
use kanidmd_testkit::*;
|
||||
|
||||
#[kanidmd_testkit::test]
|
||||
|
@ -8,12 +8,7 @@ async fn account_id_unix_token(rsclient: KanidmClient) {
|
|||
|
||||
create_user(&rsclient, "group_manager", "idm_group_manage_priv").await;
|
||||
// create test user without creating new groups
|
||||
create_user(
|
||||
&rsclient,
|
||||
NOT_ADMIN_TEST_USERNAME,
|
||||
BUILTIN_GROUP_IDM_ADMINS_V1.name,
|
||||
)
|
||||
.await;
|
||||
create_user(&rsclient, NOT_ADMIN_TEST_USERNAME, NAME_IDM_ADMINS).await;
|
||||
login_account(&rsclient, "group_manager").await;
|
||||
|
||||
let response = rsclient
|
|
@ -43,15 +43,15 @@ RUN \
|
|||
export SCCACHE_DIR=/sccache; \
|
||||
export RUSTC_WRAPPER=/usr/bin/sccache; \
|
||||
export CC="/usr/bin/clang"; \
|
||||
cargo build -p kanidm_tools ${KANIDM_BUILD_OPTIONS} \
|
||||
cargo build --locked -p kanidm_tools ${KANIDM_BUILD_OPTIONS} \
|
||||
--target-dir="/usr/src/kanidm/target/" \
|
||||
--features="${KANIDM_FEATURES}" \
|
||||
--release && \
|
||||
cargo build -p kanidm-ipa-sync ${KANIDM_BUILD_OPTIONS} \
|
||||
cargo build --locked -p kanidm-ipa-sync ${KANIDM_BUILD_OPTIONS} \
|
||||
--target-dir="/usr/src/kanidm/target/" \
|
||||
--features="${KANIDM_FEATURES}" \
|
||||
--release && \
|
||||
cargo build -p kanidm-ldap-sync ${KANIDM_BUILD_OPTIONS} \
|
||||
cargo build --locked -p kanidm-ldap-sync ${KANIDM_BUILD_OPTIONS} \
|
||||
--target-dir="/usr/src/kanidm/target/" \
|
||||
--features="${KANIDM_FEATURES}" \
|
||||
--release && \
|
||||
|
|
|
@ -22,14 +22,14 @@ dev-oauth2-device-flow = []
|
|||
[lib]
|
||||
name = "kanidm_cli"
|
||||
path = "src/cli/lib.rs"
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "kanidm"
|
||||
path = "src/cli/main.rs"
|
||||
doc = false
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -12,8 +12,8 @@ repository = { workspace = true }
|
|||
|
||||
|
||||
[lib]
|
||||
test = false
|
||||
doctest = false
|
||||
test = false
|
||||
|
||||
[features]
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ license = { workspace = true }
|
|||
homepage = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[[bin]]
|
||||
name = "kanidm-ipa-sync"
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["derive", "env"] }
|
||||
chrono = { workspace = true }
|
||||
|
|
|
@ -11,6 +11,11 @@ license = { workspace = true }
|
|||
homepage = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[[bin]]
|
||||
name = "kanidm-ldap-sync"
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["derive", "env"] }
|
||||
chrono = { workspace = true }
|
||||
|
|
|
@ -14,7 +14,7 @@ repository = { workspace = true }
|
|||
[[bin]]
|
||||
name = "orca"
|
||||
path = "src/main.rs"
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -43,7 +43,7 @@ RUN \
|
|||
export SCCACHE_DIR=/sccache; \
|
||||
export RUSTC_WRAPPER=/usr/bin/sccache; \
|
||||
export CC="/usr/bin/clang"; \
|
||||
cargo build -p orca ${KANIDM_BUILD_OPTIONS} \
|
||||
cargo build --locked -p orca ${KANIDM_BUILD_OPTIONS} \
|
||||
--target-dir="/usr/src/kanidm/target/" \
|
||||
--features="${KANIDM_FEATURES}" \
|
||||
--release && \
|
||||
|
|
|
@ -21,28 +21,28 @@ tpm = ["kanidm-hsm-crypto/tpm"]
|
|||
name = "kanidm_unixd"
|
||||
path = "src/bin/kanidm_unixd.rs"
|
||||
required-features = ["unix"]
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "kanidm_unixd_tasks"
|
||||
path = "src/bin/kanidm_unixd_tasks.rs"
|
||||
required-features = ["unix"]
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "kanidm_ssh_authorizedkeys"
|
||||
path = "src/bin/kanidm_ssh_authorizedkeys.rs"
|
||||
required-features = ["unix"]
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "kanidm-unix"
|
||||
path = "src/bin/kanidm-unix.rs"
|
||||
required-features = ["unix"]
|
||||
test = true
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -88,6 +88,7 @@ async fn setup_test(fix_fn: Fixture) -> (Resolver, KanidmClient) {
|
|||
// Run fixtures
|
||||
let adminclient = KanidmClientBuilder::new()
|
||||
.address(addr.clone())
|
||||
.enable_native_ca_roots(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.expect("Failed to build sync client");
|
||||
|
@ -96,12 +97,14 @@ async fn setup_test(fix_fn: Fixture) -> (Resolver, KanidmClient) {
|
|||
|
||||
let client = KanidmClientBuilder::new()
|
||||
.address(addr.clone())
|
||||
.enable_native_ca_roots(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.expect("Failed to build async admin client");
|
||||
|
||||
let rsclient = KanidmClientBuilder::new()
|
||||
.address(addr)
|
||||
.enable_native_ca_roots(false)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
|
|
Loading…
Reference in a new issue