mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
Update to 1.4.0-dev (#2943)
This commit is contained in:
parent
a365312076
commit
329750981e
50
Cargo.lock
generated
50
Cargo.lock
generated
|
@ -1213,7 +1213,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
|
@ -3188,7 +3188,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm-ipa-sync"
|
name = "kanidm-ipa-sync"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -3212,7 +3212,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm-ldap-sync"
|
name = "kanidm-ldap-sync"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64urlsafedata 0.5.0",
|
"base64urlsafedata 0.5.0",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -3238,7 +3238,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_build_profiles"
|
name = "kanidm_build_profiles"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"gix",
|
"gix",
|
||||||
|
@ -3248,7 +3248,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_client"
|
name = "kanidm_client"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compact_jwt 0.4.2",
|
"compact_jwt 0.4.2",
|
||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
|
@ -3269,7 +3269,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_lib_crypto"
|
name = "kanidm_lib_crypto"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
@ -3290,7 +3290,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_lib_file_permissions"
|
name = "kanidm_lib_file_permissions"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kanidm_utils_users",
|
"kanidm_utils_users",
|
||||||
"whoami",
|
"whoami",
|
||||||
|
@ -3298,7 +3298,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_proto"
|
name = "kanidm_proto"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base32",
|
"base32",
|
||||||
"base64urlsafedata 0.5.0",
|
"base64urlsafedata 0.5.0",
|
||||||
|
@ -3318,7 +3318,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_tools"
|
name = "kanidm_tools"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
|
@ -3351,7 +3351,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_unix_common"
|
name = "kanidm_unix_common"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"csv",
|
"csv",
|
||||||
|
@ -3367,7 +3367,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_unix_int"
|
name = "kanidm_unix_int"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -3407,14 +3407,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidm_utils_users"
|
name = "kanidm_utils_users"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_core"
|
name = "kanidmd_core"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -3471,7 +3471,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_lib"
|
name = "kanidmd_lib"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"base64urlsafedata 0.5.0",
|
"base64urlsafedata 0.5.0",
|
||||||
|
@ -3532,7 +3532,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_lib_macros"
|
name = "kanidmd_lib_macros"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3541,7 +3541,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_testkit"
|
name = "kanidmd_testkit"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"compact_jwt 0.4.2",
|
"compact_jwt 0.4.2",
|
||||||
|
@ -3579,7 +3579,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_web_ui_admin"
|
name = "kanidmd_web_ui_admin"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enum-iterator",
|
"enum-iterator",
|
||||||
"gloo",
|
"gloo",
|
||||||
|
@ -3601,7 +3601,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_web_ui_login_flows"
|
name = "kanidmd_web_ui_login_flows"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gloo",
|
"gloo",
|
||||||
"gloo-utils 0.2.0",
|
"gloo-utils 0.2.0",
|
||||||
|
@ -3622,7 +3622,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_web_ui_shared"
|
name = "kanidmd_web_ui_shared"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gloo",
|
"gloo",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -3641,7 +3641,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kanidmd_web_ui_user"
|
name = "kanidmd_web_ui_user"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enum-iterator",
|
"enum-iterator",
|
||||||
"gloo",
|
"gloo",
|
||||||
|
@ -4097,7 +4097,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nss_kanidm"
|
name = "nss_kanidm"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kanidm_unix_common",
|
"kanidm_unix_common",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -4470,7 +4470,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orca"
|
name = "orca"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -4513,7 +4513,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pam_kanidm"
|
name = "pam_kanidm"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kanidm_unix_common",
|
"kanidm_unix_common",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -5367,7 +5367,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scim_proto"
|
name = "scim_proto"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64urlsafedata 0.5.0",
|
"base64urlsafedata 0.5.0",
|
||||||
"peg",
|
"peg",
|
||||||
|
@ -5647,7 +5647,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sketching"
|
name = "sketching"
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gethostname",
|
"gethostname",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
|
|
28
Cargo.toml
28
Cargo.toml
|
@ -1,5 +1,5 @@
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "1.3.0-dev"
|
version = "1.4.0-dev"
|
||||||
authors = [
|
authors = [
|
||||||
"William Brown <william@blackhats.net.au>",
|
"William Brown <william@blackhats.net.au>",
|
||||||
"James Hodgkinson <james@terminaloutcomes.com>",
|
"James Hodgkinson <james@terminaloutcomes.com>",
|
||||||
|
@ -124,20 +124,20 @@ codegen-units = 256
|
||||||
# kanidm-hsm-crypto = { path = "../hsm-crypto" }
|
# kanidm-hsm-crypto = { path = "../hsm-crypto" }
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
kanidmd_core = { path = "./server/core", version = "=1.3.0-dev" }
|
kanidmd_core = { path = "./server/core", version = "=1.4.0-dev" }
|
||||||
kanidmd_lib = { path = "./server/lib", version = "=1.3.0-dev" }
|
kanidmd_lib = { path = "./server/lib", version = "=1.4.0-dev" }
|
||||||
kanidmd_lib_macros = { path = "./server/lib-macros", version = "=1.3.0-dev" }
|
kanidmd_lib_macros = { path = "./server/lib-macros", version = "=1.4.0-dev" }
|
||||||
kanidmd_testkit = { path = "./server/testkit", version = "=1.3.0-dev" }
|
kanidmd_testkit = { path = "./server/testkit", version = "=1.4.0-dev" }
|
||||||
kanidm_build_profiles = { path = "./libs/profiles", version = "=1.3.0-dev" }
|
kanidm_build_profiles = { path = "./libs/profiles", version = "=1.4.0-dev" }
|
||||||
kanidm_client = { path = "./libs/client", version = "=1.3.0-dev" }
|
kanidm_client = { path = "./libs/client", version = "=1.4.0-dev" }
|
||||||
kanidm-hsm-crypto = "^0.2.0"
|
kanidm-hsm-crypto = "^0.2.0"
|
||||||
kanidm_lib_crypto = { path = "./libs/crypto", version = "=1.3.0-dev" }
|
kanidm_lib_crypto = { path = "./libs/crypto", version = "=1.4.0-dev" }
|
||||||
kanidm_lib_file_permissions = { path = "./libs/file_permissions", version = "=1.3.0-dev" }
|
kanidm_lib_file_permissions = { path = "./libs/file_permissions", version = "=1.4.0-dev" }
|
||||||
kanidm_proto = { path = "./proto", version = "=1.3.0-dev" }
|
kanidm_proto = { path = "./proto", version = "=1.4.0-dev" }
|
||||||
kanidm_unix_common = { path = "./unix_integration/common", version = "=1.3.0-dev" }
|
kanidm_unix_common = { path = "./unix_integration/common", version = "=1.4.0-dev" }
|
||||||
kanidm_utils_users = { path = "./libs/users", version = "=1.3.0-dev" }
|
kanidm_utils_users = { path = "./libs/users", version = "=1.4.0-dev" }
|
||||||
scim_proto = { path = "./libs/scim_proto", version = "=1.3.0-dev" }
|
scim_proto = { path = "./libs/scim_proto", version = "=1.4.0-dev" }
|
||||||
sketching = { path = "./libs/sketching", version = "=1.3.0-dev" }
|
sketching = { path = "./libs/sketching", version = "=1.4.0-dev" }
|
||||||
|
|
||||||
anyhow = { version = "1.0.86" }
|
anyhow = { version = "1.0.86" }
|
||||||
argon2 = { version = "0.5.3", features = ["alloc"] }
|
argon2 = { version = "0.5.3", features = ["alloc"] }
|
||||||
|
|
|
@ -153,6 +153,7 @@ pub enum OperationError {
|
||||||
MG0005GidConstraintsNotMet,
|
MG0005GidConstraintsNotMet,
|
||||||
MG0006SKConstraintsNotMet,
|
MG0006SKConstraintsNotMet,
|
||||||
MG0007Oauth2StrictConstraintsNotMet,
|
MG0007Oauth2StrictConstraintsNotMet,
|
||||||
|
MG0008SkipUpgradeAttempted,
|
||||||
//
|
//
|
||||||
KP0001KeyProviderNotLoaded,
|
KP0001KeyProviderNotLoaded,
|
||||||
KP0002KeyProviderInvalidClass,
|
KP0002KeyProviderInvalidClass,
|
||||||
|
@ -306,6 +307,7 @@ impl OperationError {
|
||||||
Self::MG0005GidConstraintsNotMet => None,
|
Self::MG0005GidConstraintsNotMet => None,
|
||||||
Self::MG0006SKConstraintsNotMet => Some("Migration Constraints Not Met - Security Keys should not be present."),
|
Self::MG0006SKConstraintsNotMet => Some("Migration Constraints Not Met - Security Keys should not be present."),
|
||||||
Self::MG0007Oauth2StrictConstraintsNotMet => Some("Migration Constraints Not Met - All OAuth2 clients must have strict-redirect-uri mode enabled."),
|
Self::MG0007Oauth2StrictConstraintsNotMet => Some("Migration Constraints Not Met - All OAuth2 clients must have strict-redirect-uri mode enabled."),
|
||||||
|
Self::MG0008SkipUpgradeAttempted => Some("Skip Upgrade Attempted."),
|
||||||
Self::KP0001KeyProviderNotLoaded => None,
|
Self::KP0001KeyProviderNotLoaded => None,
|
||||||
Self::KP0002KeyProviderInvalidClass => None,
|
Self::KP0002KeyProviderInvalidClass => None,
|
||||||
Self::KP0003KeyProviderInvalidType => None,
|
Self::KP0003KeyProviderInvalidType => None,
|
||||||
|
|
|
@ -491,53 +491,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_V1: BuiltinAcp = BuiltinAcp {
|
|
||||||
classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::AccessControlProfile,
|
|
||||||
EntryClass::AccessControlModify,
|
|
||||||
EntryClass::AccessControlSearch
|
|
||||||
],
|
|
||||||
name: "idm_acp_group_account_policy_manage_",
|
|
||||||
uuid: UUID_IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE,
|
|
||||||
description: "Builtin IDM Control for management of account policy on groups",
|
|
||||||
receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_POLICY_ADMINS]),
|
|
||||||
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
|
||||||
match_class_filter!(EntryClass::Group),
|
|
||||||
ProtoFilter::AndNot(Box::new(FILTER_HP_OR_RECYCLED_OR_TOMBSTONE.clone())),
|
|
||||||
])),
|
|
||||||
search_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::Uuid,
|
|
||||||
Attribute::AuthSessionExpiry,
|
|
||||||
Attribute::AuthPasswordMinimumLength,
|
|
||||||
Attribute::CredentialTypeMinimum,
|
|
||||||
Attribute::PrivilegeExpiry,
|
|
||||||
Attribute::WebauthnAttestationCaList,
|
|
||||||
],
|
|
||||||
modify_removed_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::AuthSessionExpiry,
|
|
||||||
Attribute::AuthPasswordMinimumLength,
|
|
||||||
Attribute::CredentialTypeMinimum,
|
|
||||||
Attribute::PrivilegeExpiry,
|
|
||||||
Attribute::WebauthnAttestationCaList,
|
|
||||||
],
|
|
||||||
modify_present_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::AuthSessionExpiry,
|
|
||||||
Attribute::AuthPasswordMinimumLength,
|
|
||||||
Attribute::CredentialTypeMinimum,
|
|
||||||
Attribute::PrivilegeExpiry,
|
|
||||||
Attribute::WebauthnAttestationCaList,
|
|
||||||
],
|
|
||||||
modify_classes: vec![EntryClass::AccountPolicy,],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6: BuiltinAcp = BuiltinAcp {
|
pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6: BuiltinAcp = BuiltinAcp {
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
@ -591,96 +544,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref IDM_ACP_OAUTH2_MANAGE_V1: BuiltinAcp = BuiltinAcp {
|
|
||||||
classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::AccessControlProfile,
|
|
||||||
EntryClass::AccessControlCreate,
|
|
||||||
EntryClass::AccessControlDelete,
|
|
||||||
EntryClass::AccessControlModify,
|
|
||||||
EntryClass::AccessControlSearch
|
|
||||||
],
|
|
||||||
name: "idm_acp_hp_oauth2_manage_priv",
|
|
||||||
uuid: UUID_IDM_ACP_OAUTH2_MANAGE_V1,
|
|
||||||
description: "Builtin IDM Control for managing oauth2 resource server integrations.",
|
|
||||||
receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_OAUTH2_ADMINS]),
|
|
||||||
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
|
||||||
match_class_filter!(EntryClass::OAuth2ResourceServer),
|
|
||||||
FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(),
|
|
||||||
])),
|
|
||||||
search_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::DisplayName,
|
|
||||||
Attribute::OAuth2RsName,
|
|
||||||
Attribute::OAuth2RsOrigin,
|
|
||||||
Attribute::OAuth2RsOriginLanding,
|
|
||||||
Attribute::OAuth2RsScopeMap,
|
|
||||||
Attribute::OAuth2RsSupScopeMap,
|
|
||||||
Attribute::OAuth2RsBasicSecret,
|
|
||||||
Attribute::OAuth2RsTokenKey,
|
|
||||||
Attribute::Es256PrivateKeyDer,
|
|
||||||
Attribute::OAuth2AllowInsecureClientDisablePkce,
|
|
||||||
Attribute::Rs256PrivateKeyDer,
|
|
||||||
Attribute::OAuth2JwtLegacyCryptoEnable,
|
|
||||||
Attribute::OAuth2PreferShortUsername,
|
|
||||||
Attribute::Image,
|
|
||||||
],
|
|
||||||
modify_removed_attrs: vec![
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::DisplayName,
|
|
||||||
Attribute::OAuth2RsName,
|
|
||||||
Attribute::OAuth2RsOrigin,
|
|
||||||
Attribute::OAuth2RsOriginLanding,
|
|
||||||
Attribute::OAuth2RsScopeMap,
|
|
||||||
Attribute::OAuth2RsSupScopeMap,
|
|
||||||
Attribute::OAuth2RsBasicSecret,
|
|
||||||
Attribute::OAuth2RsTokenKey,
|
|
||||||
Attribute::Es256PrivateKeyDer,
|
|
||||||
Attribute::OAuth2AllowInsecureClientDisablePkce,
|
|
||||||
Attribute::Rs256PrivateKeyDer,
|
|
||||||
Attribute::OAuth2JwtLegacyCryptoEnable,
|
|
||||||
Attribute::OAuth2PreferShortUsername,
|
|
||||||
Attribute::Image,
|
|
||||||
],
|
|
||||||
modify_present_attrs: vec![
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::DisplayName,
|
|
||||||
Attribute::OAuth2RsName,
|
|
||||||
Attribute::OAuth2RsOrigin,
|
|
||||||
Attribute::OAuth2RsOriginLanding,
|
|
||||||
Attribute::OAuth2RsSupScopeMap,
|
|
||||||
Attribute::OAuth2RsScopeMap,
|
|
||||||
Attribute::OAuth2AllowInsecureClientDisablePkce,
|
|
||||||
Attribute::OAuth2JwtLegacyCryptoEnable,
|
|
||||||
Attribute::OAuth2PreferShortUsername,
|
|
||||||
Attribute::Image,
|
|
||||||
],
|
|
||||||
create_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::DisplayName,
|
|
||||||
Attribute::OAuth2RsName,
|
|
||||||
Attribute::OAuth2RsOrigin,
|
|
||||||
Attribute::OAuth2RsOriginLanding,
|
|
||||||
Attribute::OAuth2RsSupScopeMap,
|
|
||||||
Attribute::OAuth2RsScopeMap,
|
|
||||||
Attribute::OAuth2AllowInsecureClientDisablePkce,
|
|
||||||
Attribute::OAuth2JwtLegacyCryptoEnable,
|
|
||||||
Attribute::OAuth2PreferShortUsername,
|
|
||||||
Attribute::Image,
|
|
||||||
],
|
|
||||||
create_classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::OAuth2ResourceServer,
|
|
||||||
EntryClass::OAuth2ResourceServerBasic,
|
|
||||||
EntryClass::OAuth2ResourceServerPublic,
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_OAUTH2_MANAGE_DL4: BuiltinAcp = BuiltinAcp {
|
pub static ref IDM_ACP_OAUTH2_MANAGE_DL4: BuiltinAcp = BuiltinAcp {
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
@ -858,6 +721,7 @@ lazy_static! {
|
||||||
Attribute::Class,
|
Attribute::Class,
|
||||||
Attribute::Description,
|
Attribute::Description,
|
||||||
Attribute::Name,
|
Attribute::Name,
|
||||||
|
Attribute::DisplayName,
|
||||||
Attribute::OAuth2RsName,
|
Attribute::OAuth2RsName,
|
||||||
Attribute::OAuth2RsOrigin,
|
Attribute::OAuth2RsOrigin,
|
||||||
Attribute::OAuth2RsOriginLanding,
|
Attribute::OAuth2RsOriginLanding,
|
||||||
|
@ -963,6 +827,7 @@ lazy_static! {
|
||||||
Attribute::Class,
|
Attribute::Class,
|
||||||
Attribute::Description,
|
Attribute::Description,
|
||||||
Attribute::Name,
|
Attribute::Name,
|
||||||
|
Attribute::DisplayName,
|
||||||
Attribute::OAuth2RsName,
|
Attribute::OAuth2RsName,
|
||||||
Attribute::OAuth2RsOrigin,
|
Attribute::OAuth2RsOrigin,
|
||||||
Attribute::OAuth2RsOriginLanding,
|
Attribute::OAuth2RsOriginLanding,
|
||||||
|
@ -987,59 +852,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref IDM_ACP_DOMAIN_ADMIN_V1: BuiltinAcp = BuiltinAcp {
|
|
||||||
classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::AccessControlProfile,
|
|
||||||
EntryClass::AccessControlModify,
|
|
||||||
EntryClass::AccessControlSearch
|
|
||||||
],
|
|
||||||
name: "idm_acp_domain_admin",
|
|
||||||
uuid: UUID_IDM_ACP_DOMAIN_ADMIN_V1,
|
|
||||||
description: "Builtin IDM Control for granting domain info administration locally",
|
|
||||||
receiver: BuiltinAcpReceiver::Group(vec![UUID_DOMAIN_ADMINS]),
|
|
||||||
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
|
||||||
ProtoFilter::Eq(
|
|
||||||
Attribute::Uuid.to_string(),
|
|
||||||
STR_UUID_DOMAIN_INFO.to_string()
|
|
||||||
),
|
|
||||||
FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone()
|
|
||||||
])),
|
|
||||||
search_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::Uuid,
|
|
||||||
Attribute::DomainDisplayName,
|
|
||||||
Attribute::DomainName,
|
|
||||||
Attribute::DomainLdapBasedn,
|
|
||||||
Attribute::DomainSsid,
|
|
||||||
Attribute::DomainUuid,
|
|
||||||
Attribute::Es256PrivateKeyDer,
|
|
||||||
Attribute::FernetPrivateKeyStr,
|
|
||||||
Attribute::CookiePrivateKey,
|
|
||||||
Attribute::LdapAllowUnixPwBind,
|
|
||||||
Attribute::Version,
|
|
||||||
],
|
|
||||||
modify_removed_attrs: vec![
|
|
||||||
Attribute::DomainDisplayName,
|
|
||||||
Attribute::DomainSsid,
|
|
||||||
Attribute::DomainLdapBasedn,
|
|
||||||
Attribute::Es256PrivateKeyDer,
|
|
||||||
Attribute::CookiePrivateKey,
|
|
||||||
Attribute::FernetPrivateKeyStr,
|
|
||||||
Attribute::LdapAllowUnixPwBind,
|
|
||||||
],
|
|
||||||
modify_present_attrs: vec![
|
|
||||||
Attribute::DomainDisplayName,
|
|
||||||
Attribute::DomainLdapBasedn,
|
|
||||||
Attribute::DomainSsid,
|
|
||||||
Attribute::LdapAllowUnixPwBind,
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_DOMAIN_ADMIN_DL6: BuiltinAcp = BuiltinAcp {
|
pub static ref IDM_ACP_DOMAIN_ADMIN_DL6: BuiltinAcp = BuiltinAcp {
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
@ -1479,26 +1291,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref IDM_ACP_ACCOUNT_MAIL_READ_V1: BuiltinAcp = BuiltinAcp {
|
|
||||||
classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::AccessControlProfile,
|
|
||||||
EntryClass::AccessControlSearch
|
|
||||||
],
|
|
||||||
name: "idm_acp_account_mail_read",
|
|
||||||
uuid: UUID_IDM_ACP_ACCOUNT_MAIL_READ_V1,
|
|
||||||
description: "Builtin IDM Control for reading account mail attributes.",
|
|
||||||
receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_MAIL_READ]),
|
|
||||||
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
|
||||||
match_class_filter!(EntryClass::Account),
|
|
||||||
FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(),
|
|
||||||
])),
|
|
||||||
search_attrs: vec![Attribute::Mail],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_ACCOUNT_MAIL_READ_DL6: BuiltinAcp = BuiltinAcp {
|
pub static ref IDM_ACP_ACCOUNT_MAIL_READ_DL6: BuiltinAcp = BuiltinAcp {
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
@ -1610,61 +1402,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref IDM_ACP_GROUP_MANAGE_V1: BuiltinAcp = BuiltinAcp{
|
|
||||||
classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::AccessControlProfile,
|
|
||||||
EntryClass::AccessControlCreate,
|
|
||||||
EntryClass::AccessControlDelete,
|
|
||||||
EntryClass::AccessControlModify,
|
|
||||||
EntryClass::AccessControlSearch
|
|
||||||
],
|
|
||||||
name: "idm_acp_group_manage",
|
|
||||||
uuid: UUID_IDM_ACP_GROUP_MANAGE_V1,
|
|
||||||
description: "Builtin IDM Control for creating and deleting groups in the directory",
|
|
||||||
receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_GROUP_ADMINS] ),
|
|
||||||
// group which is not in HP, Recycled, Tombstone
|
|
||||||
target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![
|
|
||||||
match_class_filter!(EntryClass::Group),
|
|
||||||
FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(),
|
|
||||||
])),
|
|
||||||
search_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::Uuid,
|
|
||||||
Attribute::Spn,
|
|
||||||
Attribute::Uuid,
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::Member,
|
|
||||||
Attribute::DynMember,
|
|
||||||
Attribute::EntryManagedBy,
|
|
||||||
],
|
|
||||||
create_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::Member,
|
|
||||||
Attribute::EntryManagedBy,
|
|
||||||
],
|
|
||||||
create_classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::Group,
|
|
||||||
],
|
|
||||||
modify_present_attrs: vec![
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::Member,
|
|
||||||
],
|
|
||||||
modify_removed_attrs: vec![
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::Description,
|
|
||||||
Attribute::Member,
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_GROUP_MANAGE_DL6: BuiltinAcp = BuiltinAcp{
|
pub static ref IDM_ACP_GROUP_MANAGE_DL6: BuiltinAcp = BuiltinAcp{
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
@ -1862,39 +1599,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Person Account Create
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref IDM_ACP_PEOPLE_CREATE_V1: BuiltinAcp = BuiltinAcp {
|
|
||||||
classes: vec![
|
|
||||||
EntryClass::Object,
|
|
||||||
EntryClass::AccessControlProfile,
|
|
||||||
EntryClass::AccessControlCreate,
|
|
||||||
],
|
|
||||||
name: "idm_acp_people_create",
|
|
||||||
uuid: UUID_IDM_ACP_PEOPLE_CREATE_V1,
|
|
||||||
description: "Builtin IDM Control for creating new persons.",
|
|
||||||
receiver: BuiltinAcpReceiver::Group(vec![
|
|
||||||
UUID_IDM_PEOPLE_ADMINS,
|
|
||||||
UUID_IDM_PEOPLE_ON_BOARDING
|
|
||||||
]),
|
|
||||||
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
|
||||||
match_class_filter!(EntryClass::Person).clone(),
|
|
||||||
match_class_filter!(EntryClass::Account).clone(),
|
|
||||||
FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(),
|
|
||||||
])),
|
|
||||||
create_attrs: vec![
|
|
||||||
Attribute::Class,
|
|
||||||
Attribute::Name,
|
|
||||||
Attribute::DisplayName,
|
|
||||||
Attribute::Mail,
|
|
||||||
Attribute::AccountExpire,
|
|
||||||
Attribute::AccountValidFrom,
|
|
||||||
],
|
|
||||||
create_classes: vec![EntryClass::Object, EntryClass::Account, EntryClass::Person,],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_PEOPLE_CREATE_DL6: BuiltinAcp = BuiltinAcp {
|
pub static ref IDM_ACP_PEOPLE_CREATE_DL6: BuiltinAcp = BuiltinAcp {
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
|
|
@ -800,18 +800,6 @@ lazy_static! {
|
||||||
(Attribute::Version, Value::Uint32(20))
|
(Attribute::Version, Value::Uint32(20))
|
||||||
);
|
);
|
||||||
|
|
||||||
pub static ref E_DOMAIN_INFO_V1: EntryInitNew = entry_init!(
|
|
||||||
(Attribute::Class, EntryClass::Object.to_value()),
|
|
||||||
(Attribute::Class, EntryClass::DomainInfo.to_value()),
|
|
||||||
(Attribute::Class, EntryClass::System.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_DOMAIN_INFO_DL6: EntryInitNew = entry_init!(
|
pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!(
|
||||||
(Attribute::Class, EntryClass::Object.to_value()),
|
(Attribute::Class, EntryClass::Object.to_value()),
|
||||||
(Attribute::Class, EntryClass::DomainInfo.to_value()),
|
(Attribute::Class, EntryClass::DomainInfo.to_value()),
|
||||||
|
@ -916,17 +904,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_V1: BuiltinAccount = BuiltinAccount {
|
|
||||||
account_type: AccountType::ServiceAccount,
|
|
||||||
entry_managed_by: None,
|
|
||||||
name: "anonymous",
|
|
||||||
uuid: UUID_ANONYMOUS,
|
|
||||||
description: "Anonymous access account.",
|
|
||||||
displayname: "Anonymous",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount {
|
pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount {
|
||||||
account_type: AccountType::ServiceAccount,
|
account_type: AccountType::ServiceAccount,
|
||||||
|
@ -940,9 +917,9 @@ lazy_static! {
|
||||||
|
|
||||||
pub fn builtin_accounts() -> Vec<&'static BuiltinAccount> {
|
pub fn builtin_accounts() -> Vec<&'static BuiltinAccount> {
|
||||||
vec![
|
vec![
|
||||||
&BUILTIN_ACCOUNT_ANONYMOUS_V1,
|
|
||||||
&BUILTIN_ACCOUNT_ADMIN,
|
&BUILTIN_ACCOUNT_ADMIN,
|
||||||
&BUILTIN_ACCOUNT_IDM_ADMIN,
|
&BUILTIN_ACCOUNT_IDM_ADMIN,
|
||||||
|
&BUILTIN_ACCOUNT_ANONYMOUS_DL6,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,7 +958,6 @@ lazy_static! {
|
||||||
/// Build a list of internal admin entries
|
/// Build a list of internal admin entries
|
||||||
pub fn idm_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
pub fn idm_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError> {
|
||||||
let mut res: Vec<EntryInitNew> = vec![
|
let mut res: Vec<EntryInitNew> = vec![
|
||||||
BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into(),
|
|
||||||
BUILTIN_ACCOUNT_ADMIN.clone().into(),
|
BUILTIN_ACCOUNT_ADMIN.clone().into(),
|
||||||
BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(),
|
BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(),
|
||||||
];
|
];
|
||||||
|
@ -989,5 +965,9 @@ pub fn idm_builtin_admin_entries() -> Result<Vec<EntryInitNew>, OperationError>
|
||||||
let g: EntryInitNew = group.clone().try_into()?;
|
let g: EntryInitNew = group.clone().try_into()?;
|
||||||
res.push(g);
|
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)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,15 +52,6 @@ pub type DomainVersion = u32;
|
||||||
/// previously.
|
/// previously.
|
||||||
pub const DOMAIN_LEVEL_0: DomainVersion = 0;
|
pub const DOMAIN_LEVEL_0: DomainVersion = 0;
|
||||||
|
|
||||||
/// Deprcated as of 1.2.0
|
|
||||||
pub const DOMAIN_LEVEL_1: DomainVersion = 1;
|
|
||||||
/// Deprcated as of 1.2.0
|
|
||||||
pub const DOMAIN_LEVEL_2: DomainVersion = 2;
|
|
||||||
/// Deprcated as of 1.2.0
|
|
||||||
pub const DOMAIN_LEVEL_3: DomainVersion = 3;
|
|
||||||
/// Deprcated as of 1.2.0
|
|
||||||
pub const DOMAIN_LEVEL_4: DomainVersion = 4;
|
|
||||||
|
|
||||||
/// Deprcated as of 1.3.0
|
/// Deprcated as of 1.3.0
|
||||||
pub const DOMAIN_LEVEL_5: DomainVersion = 5;
|
pub const DOMAIN_LEVEL_5: DomainVersion = 5;
|
||||||
|
|
||||||
|
@ -77,22 +68,26 @@ pub const DOMAIN_LEVEL_7: DomainVersion = 7;
|
||||||
/// Deprcated as of 1.6.0
|
/// Deprcated as of 1.6.0
|
||||||
pub const DOMAIN_LEVEL_8: DomainVersion = 8;
|
pub const DOMAIN_LEVEL_8: DomainVersion = 8;
|
||||||
|
|
||||||
|
/// Domain Level introduced with 1.5.0.
|
||||||
|
/// Deprcated as of 1.7.0
|
||||||
|
pub const DOMAIN_LEVEL_9: DomainVersion = 9;
|
||||||
|
|
||||||
// The minimum level that we can re-migrate from.
|
// The minimum level that we can re-migrate from.
|
||||||
// This should be DOMAIN_TGT_LEVEL minus 2
|
// This should be DOMAIN_TGT_LEVEL minus 2
|
||||||
pub const DOMAIN_MIN_REMIGRATION_LEVEL: DomainVersion = DOMAIN_LEVEL_5;
|
pub const DOMAIN_MIN_REMIGRATION_LEVEL: DomainVersion = DOMAIN_LEVEL_6;
|
||||||
// The minimum supported domain functional level
|
// The minimum supported domain functional level (for replication)
|
||||||
pub const DOMAIN_MIN_LEVEL: DomainVersion = DOMAIN_TGT_LEVEL;
|
pub const DOMAIN_MIN_LEVEL: DomainVersion = DOMAIN_TGT_LEVEL;
|
||||||
// The previous releases domain functional level
|
// The previous releases domain functional level
|
||||||
pub const DOMAIN_PREVIOUS_TGT_LEVEL: DomainVersion = DOMAIN_LEVEL_6;
|
pub const DOMAIN_PREVIOUS_TGT_LEVEL: DomainVersion = DOMAIN_LEVEL_7;
|
||||||
// The target supported domain functional level. During development this is
|
// The target supported domain functional level. During development this is
|
||||||
// the NEXT level that users will upgrade too.
|
// the NEXT level that users will upgrade too.
|
||||||
pub const DOMAIN_TGT_LEVEL: DomainVersion = DOMAIN_LEVEL_7;
|
pub const DOMAIN_TGT_LEVEL: DomainVersion = DOMAIN_LEVEL_8;
|
||||||
// The current patch level if any out of band fixes are required.
|
// The current patch level if any out of band fixes are required.
|
||||||
pub const DOMAIN_TGT_PATCH_LEVEL: u32 = PATCH_LEVEL_1;
|
pub const DOMAIN_TGT_PATCH_LEVEL: u32 = PATCH_LEVEL_1;
|
||||||
// The target domain functional level for the SUBSEQUENT release/dev cycle.
|
// The target domain functional level for the SUBSEQUENT release/dev cycle.
|
||||||
pub const DOMAIN_TGT_NEXT_LEVEL: DomainVersion = DOMAIN_LEVEL_8;
|
pub const DOMAIN_TGT_NEXT_LEVEL: DomainVersion = DOMAIN_LEVEL_9;
|
||||||
// The maximum supported domain functional level
|
// The maximum supported domain functional level
|
||||||
pub const DOMAIN_MAX_LEVEL: DomainVersion = DOMAIN_LEVEL_8;
|
pub const DOMAIN_MAX_LEVEL: DomainVersion = DOMAIN_LEVEL_9;
|
||||||
|
|
||||||
// On test builds define to 60 seconds
|
// On test builds define to 60 seconds
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -839,23 +839,6 @@ pub static ref SCHEMA_CLASS_ORGPERSON: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_GROUP: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_GROUP,
|
|
||||||
name: EntryClass::Group.into(),
|
|
||||||
description: "Object representation of a group".to_string(),
|
|
||||||
|
|
||||||
sync_allowed: true,
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::Member.into(),
|
|
||||||
Attribute::GrantUiHint.into(),
|
|
||||||
Attribute::Description.into()
|
|
||||||
],
|
|
||||||
systemmust: vec![
|
|
||||||
Attribute::Name.into(),
|
|
||||||
Attribute::Spn.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_GROUP_DL6: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_GROUP_DL6: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_GROUP,
|
uuid: UUID_SCHEMA_CLASS_GROUP,
|
||||||
name: EntryClass::Group.into(),
|
name: EntryClass::Group.into(),
|
||||||
|
@ -885,22 +868,6 @@ pub static ref SCHEMA_CLASS_DYNGROUP: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_ACCOUNT_POLICY: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_ACCOUNT_POLICY,
|
|
||||||
name: EntryClass::AccountPolicy.into(),
|
|
||||||
description: "Policies applied to accounts that are members of a group".to_string(),
|
|
||||||
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::AuthSessionExpiry.into(),
|
|
||||||
Attribute::PrivilegeExpiry.into(),
|
|
||||||
Attribute::AuthPasswordMinimumLength.into(),
|
|
||||||
Attribute::CredentialTypeMinimum.into(),
|
|
||||||
Attribute::WebauthnAttestationCaList.into(),
|
|
||||||
],
|
|
||||||
systemsupplements: vec![Attribute::Group.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_ACCOUNT_POLICY_DL6: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_ACCOUNT_POLICY_DL6: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_ACCOUNT_POLICY,
|
uuid: UUID_SCHEMA_CLASS_ACCOUNT_POLICY,
|
||||||
name: EntryClass::AccountPolicy.into(),
|
name: EntryClass::AccountPolicy.into(),
|
||||||
|
@ -977,43 +944,6 @@ pub static ref SCHEMA_CLASS_ACCOUNT_DL5: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_SERVICE_ACCOUNT,
|
|
||||||
name: EntryClass::ServiceAccount.into(),
|
|
||||||
description: "Object representation of service account".to_string(),
|
|
||||||
|
|
||||||
sync_allowed: true,
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::Mail.into(),
|
|
||||||
Attribute::PrimaryCredential.into(),
|
|
||||||
Attribute::JwsEs256PrivateKey.into(),
|
|
||||||
Attribute::ApiTokenSession.into(),
|
|
||||||
],
|
|
||||||
systemexcludes: vec![EntryClass::Person.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL5: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_SERVICE_ACCOUNT,
|
|
||||||
name: EntryClass::ServiceAccount.into(),
|
|
||||||
description: "Object representation of service account".to_string(),
|
|
||||||
|
|
||||||
sync_allowed: true,
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::SshPublicKey.into(),
|
|
||||||
Attribute::UserAuthTokenSession.into(),
|
|
||||||
Attribute::OAuth2Session.into(),
|
|
||||||
Attribute::Description.into(),
|
|
||||||
|
|
||||||
Attribute::Mail.into(),
|
|
||||||
Attribute::PrimaryCredential.into(),
|
|
||||||
Attribute::JwsEs256PrivateKey.into(),
|
|
||||||
Attribute::ApiTokenSession.into(),
|
|
||||||
],
|
|
||||||
systemexcludes: vec![EntryClass::Person.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL6: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL6: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_SERVICE_ACCOUNT,
|
uuid: UUID_SCHEMA_CLASS_SERVICE_ACCOUNT,
|
||||||
name: EntryClass::ServiceAccount.into(),
|
name: EntryClass::ServiceAccount.into(),
|
||||||
|
@ -1058,22 +988,6 @@ pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL7: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_SYNC_ACCOUNT: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT,
|
|
||||||
name: EntryClass::SyncAccount.into(),
|
|
||||||
description: "Object representation of sync account".to_string(),
|
|
||||||
|
|
||||||
systemmust: vec![Attribute::Name.into(), Attribute::JwsEs256PrivateKey.into()],
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::SyncTokenSession.into(),
|
|
||||||
Attribute::SyncCookie.into(),
|
|
||||||
Attribute::SyncCredentialPortal.into(),
|
|
||||||
Attribute::SyncYieldAuthority.into(),
|
|
||||||
],
|
|
||||||
systemexcludes: vec![EntryClass::Account.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL6: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL6: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT,
|
uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT,
|
||||||
name: EntryClass::SyncAccount.into(),
|
name: EntryClass::SyncAccount.into(),
|
||||||
|
@ -1107,29 +1021,6 @@ pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL7: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_DOMAIN_INFO: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO,
|
|
||||||
name: EntryClass::DomainInfo.into(),
|
|
||||||
description: "Local domain information and partial configuration".to_string(),
|
|
||||||
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::DomainSsid.into(),
|
|
||||||
Attribute::DomainLdapBasedn.into(),
|
|
||||||
Attribute::LdapAllowUnixPwBind.into()
|
|
||||||
],
|
|
||||||
systemmust: vec![
|
|
||||||
Attribute::Name.into(),
|
|
||||||
Attribute::DomainUuid.into(),
|
|
||||||
Attribute::DomainName.into(),
|
|
||||||
Attribute::DomainDisplayName.into(),
|
|
||||||
Attribute::FernetPrivateKeyStr.into(),
|
|
||||||
Attribute::Es256PrivateKeyDer.into(),
|
|
||||||
Attribute::PrivateCookieKey.into(),
|
|
||||||
Attribute::Version.into(),
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL6: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL6: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO,
|
uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO,
|
||||||
name: EntryClass::DomainInfo.into(),
|
name: EntryClass::DomainInfo.into(),
|
||||||
|
@ -1213,31 +1104,6 @@ pub static ref SCHEMA_CLASS_SYSTEM_CONFIG: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_OAUTH2_RS: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS,
|
|
||||||
name: EntryClass::OAuth2ResourceServer.into(),
|
|
||||||
description: "The class representing a configured Oauth2 Resource Server".to_string(),
|
|
||||||
|
|
||||||
systemmay: vec![
|
|
||||||
Attribute::Description.into(),
|
|
||||||
Attribute::OAuth2RsScopeMap.into(),
|
|
||||||
Attribute::OAuth2RsSupScopeMap.into(),
|
|
||||||
Attribute::Rs256PrivateKeyDer.into(),
|
|
||||||
Attribute::OAuth2JwtLegacyCryptoEnable.into(),
|
|
||||||
Attribute::OAuth2PreferShortUsername.into(),
|
|
||||||
Attribute::OAuth2RsOriginLanding.into(),
|
|
||||||
Attribute::Image.into(),
|
|
||||||
],
|
|
||||||
systemmust: vec![
|
|
||||||
Attribute::OAuth2RsName.into(),
|
|
||||||
Attribute::DisplayName.into(),
|
|
||||||
Attribute::OAuth2RsOrigin.into(),
|
|
||||||
Attribute::OAuth2RsTokenKey.into(),
|
|
||||||
Attribute::Es256PrivateKeyDer.into(),
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_OAUTH2_RS_DL4: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_OAUTH2_RS_DL4: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS,
|
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS,
|
||||||
name: EntryClass::OAuth2ResourceServer.into(),
|
name: EntryClass::OAuth2ResourceServer.into(),
|
||||||
|
@ -1315,17 +1181,6 @@ pub static ref SCHEMA_CLASS_OAUTH2_RS_DL7: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_OAUTH2_RS_BASIC: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC,
|
|
||||||
name: EntryClass::OAuth2ResourceServerBasic.into(),
|
|
||||||
description: "The class representing a configured Oauth2 Resource Server authenticated with http basic authentication".to_string(),
|
|
||||||
|
|
||||||
systemmay: vec![ Attribute::OAuth2AllowInsecureClientDisablePkce.into()],
|
|
||||||
systemmust: vec![ Attribute::OAuth2RsBasicSecret.into()],
|
|
||||||
systemexcludes: vec![ EntryClass::OAuth2ResourceServerPublic.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC,
|
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC,
|
||||||
name: EntryClass::OAuth2ResourceServerBasic.into(),
|
name: EntryClass::OAuth2ResourceServerBasic.into(),
|
||||||
|
@ -1339,15 +1194,6 @@ pub static ref SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_OAUTH2_RS_PUBLIC: SchemaClass = SchemaClass {
|
|
||||||
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_PUBLIC,
|
|
||||||
name: EntryClass::OAuth2ResourceServerPublic.into(),
|
|
||||||
description: "The class representing a configured Oauth2 Resource Server with public clients and pkce verification".to_string(),
|
|
||||||
|
|
||||||
systemexcludes: vec![EntryClass::OAuth2ResourceServerBasic.into()],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Introduced in DomainLevel4
|
// Introduced in DomainLevel4
|
||||||
pub static ref SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_PUBLIC,
|
uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_PUBLIC,
|
||||||
|
|
|
@ -970,7 +970,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_idm_account_from_anonymous() {
|
fn test_idm_account_from_anonymous() {
|
||||||
let account: Account = BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into();
|
let account: Account = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||||
debug!("{:?}", account);
|
debug!("{:?}", account);
|
||||||
// I think that's it? we may want to check anonymous mech ...
|
// I think that's it? we may want to check anonymous mech ...
|
||||||
}
|
}
|
||||||
|
|
|
@ -1732,7 +1732,7 @@ mod tests {
|
||||||
|
|
||||||
let webauthn = create_webauthn();
|
let webauthn = create_webauthn();
|
||||||
|
|
||||||
let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into();
|
let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||||
|
|
||||||
let asd = AuthSessionData {
|
let asd = AuthSessionData {
|
||||||
account: anon_account,
|
account: anon_account,
|
||||||
|
|
|
@ -1521,8 +1521,6 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::idm::server::{IdmServerProxyWriteTransaction, IdmServerTransaction};
|
use crate::idm::server::{IdmServerProxyWriteTransaction, IdmServerTransaction};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::server::keys::KeyProvidersTransaction;
|
|
||||||
use crate::value::KeyStatus;
|
|
||||||
use compact_jwt::traits::JwsVerifiable;
|
use compact_jwt::traits::JwsVerifiable;
|
||||||
use compact_jwt::{Jws, JwsCompact, JwsEs256Signer, JwsSigner};
|
use compact_jwt::{Jws, JwsCompact, JwsEs256Signer, JwsSigner};
|
||||||
use kanidm_proto::internal::ApiTokenPurpose;
|
use kanidm_proto::internal::ApiTokenPurpose;
|
||||||
|
@ -1730,117 +1728,6 @@ mod tests {
|
||||||
assert!(matches!(fail, Err(OperationError::NotAuthenticated)));
|
assert!(matches!(fail, Err(OperationError::NotAuthenticated)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idm_test(domain_level=DOMAIN_LEVEL_5)]
|
|
||||||
async fn test_idm_scim_sync_token_dl5_dl6_token(
|
|
||||||
idms: &IdmServer,
|
|
||||||
_idms_delayed: &mut IdmServerDelayed,
|
|
||||||
) {
|
|
||||||
let ct = Duration::from_secs(TEST_CURRENT_TIME);
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
idms_prox_write.qs_write.get_domain_version(),
|
|
||||||
DOMAIN_LEVEL_5
|
|
||||||
);
|
|
||||||
|
|
||||||
let sync_uuid = Uuid::new_v4();
|
|
||||||
|
|
||||||
let e1 = entry_init!(
|
|
||||||
(Attribute::Class, EntryClass::Object.to_value()),
|
|
||||||
(Attribute::Class, EntryClass::SyncAccount.to_value()),
|
|
||||||
(Attribute::Name, Value::new_iname("test_scim_sync")),
|
|
||||||
(Attribute::Uuid, Value::Uuid(sync_uuid)),
|
|
||||||
(
|
|
||||||
Attribute::Description,
|
|
||||||
Value::new_utf8s("A test sync agreement")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_create(vec![e1])
|
|
||||||
.expect("Failed to create sync account");
|
|
||||||
|
|
||||||
let gte = GenerateScimSyncTokenEvent::new_internal(sync_uuid, "Sync Connector");
|
|
||||||
|
|
||||||
let old_sync_token = idms_prox_write
|
|
||||||
.scim_sync_generate_token(>e, ct)
|
|
||||||
.expect("failed to generate new scim sync token");
|
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// Now trigger 5 -> 6
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_apply_domain_migration(DOMAIN_LEVEL_6)
|
|
||||||
.expect("Unable to set domain level to version 6");
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// Check existing token still validates.
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
|
|
||||||
let _ident = idms_prox_write
|
|
||||||
.validate_sync_client_auth_info_to_ident(old_sync_token.clone().into(), ct)
|
|
||||||
.expect("Failed to process old sync token to ident");
|
|
||||||
|
|
||||||
// Delete the old session else we get a schema violation
|
|
||||||
let modlist = ModifyList::new_purge(Attribute::SyncTokenSession.into());
|
|
||||||
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_modify_uuid(sync_uuid, &modlist)
|
|
||||||
.expect("Unable to delete previous sync token session");
|
|
||||||
|
|
||||||
let gte = GenerateScimSyncTokenEvent::new_internal(sync_uuid, "Sync Connector");
|
|
||||||
|
|
||||||
let new_sync_token = idms_prox_write
|
|
||||||
.scim_sync_generate_token(>e, ct)
|
|
||||||
.expect("failed to generate new scim sync token");
|
|
||||||
|
|
||||||
assert_ne!(old_sync_token.kid(), new_sync_token.kid());
|
|
||||||
|
|
||||||
let _ident = idms_prox_write
|
|
||||||
.validate_sync_client_auth_info_to_ident(new_sync_token.into(), ct)
|
|
||||||
.expect("Failed to process new sync token to ident");
|
|
||||||
|
|
||||||
// The former key is now on the domain object.
|
|
||||||
let key_object = idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.get_key_providers()
|
|
||||||
.get_key_object(UUID_DOMAIN_INFO)
|
|
||||||
.expect("Unable to retrieve key object by uuid");
|
|
||||||
|
|
||||||
// Assert the former key is now in the domain key object, and now is "retained".
|
|
||||||
let former_kid = old_sync_token.kid().unwrap().to_string();
|
|
||||||
let status = key_object
|
|
||||||
.kid_status(&former_kid)
|
|
||||||
.expect("Failed to access kid status");
|
|
||||||
assert_eq!(status, Some(KeyStatus::Retained));
|
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// Now trigger 6 -> 7
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_apply_domain_migration(DOMAIN_LEVEL_7)
|
|
||||||
.expect("Unable to set domain level to version 7");
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// The key on the service account is removed.
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
|
|
||||||
let sync_entry = idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_search_uuid(sync_uuid)
|
|
||||||
.expect("Unable to access service account");
|
|
||||||
|
|
||||||
assert!(!sync_entry.attribute_pres(Attribute::JwsEs256PrivateKey));
|
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_scim_sync_apply_setup_ident(
|
fn test_scim_sync_apply_setup_ident(
|
||||||
idms_prox_write: &mut IdmServerProxyWriteTransaction,
|
idms_prox_write: &mut IdmServerProxyWriteTransaction,
|
||||||
ct: Duration,
|
ct: Duration,
|
||||||
|
|
|
@ -423,15 +423,12 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use compact_jwt::traits::JwsVerifiable;
|
|
||||||
use compact_jwt::{dangernoverify::JwsDangerReleaseWithoutVerify, JwsVerifier};
|
use compact_jwt::{dangernoverify::JwsDangerReleaseWithoutVerify, JwsVerifier};
|
||||||
use kanidm_proto::internal::ApiToken;
|
use kanidm_proto::internal::ApiToken;
|
||||||
|
|
||||||
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent};
|
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent};
|
||||||
use crate::idm::server::IdmServerTransaction;
|
use crate::idm::server::IdmServerTransaction;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::server::keys::KeyProvidersTransaction;
|
|
||||||
use crate::value::KeyStatus;
|
|
||||||
|
|
||||||
const TEST_CURRENT_TIME: u64 = 6000;
|
const TEST_CURRENT_TIME: u64 = 6000;
|
||||||
|
|
||||||
|
@ -520,112 +517,4 @@ mod tests {
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
assert!(idms_prox_write.commit().is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idm_test(domain_level=DOMAIN_LEVEL_5)]
|
|
||||||
async fn test_idm_service_account_dl5_dl6_api_token(
|
|
||||||
idms: &IdmServer,
|
|
||||||
_idms_delayed: &mut IdmServerDelayed,
|
|
||||||
) {
|
|
||||||
let ct = Duration::from_secs(TEST_CURRENT_TIME);
|
|
||||||
let exp = Duration::from_secs(TEST_CURRENT_TIME + 6000);
|
|
||||||
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
idms_prox_write.qs_write.get_domain_version(),
|
|
||||||
DOMAIN_LEVEL_5
|
|
||||||
);
|
|
||||||
|
|
||||||
let testaccount_uuid = Uuid::new_v4();
|
|
||||||
|
|
||||||
let e1 = entry_init!(
|
|
||||||
(Attribute::Class, EntryClass::Object.to_value()),
|
|
||||||
(Attribute::Class, EntryClass::Account.to_value()),
|
|
||||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
|
||||||
(Attribute::Name, Value::new_iname("test_account_only")),
|
|
||||||
(Attribute::Uuid, Value::Uuid(testaccount_uuid)),
|
|
||||||
(Attribute::Description, Value::new_utf8s("testaccount")),
|
|
||||||
(Attribute::DisplayName, Value::new_utf8s("testaccount"))
|
|
||||||
);
|
|
||||||
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_create(vec![e1])
|
|
||||||
.expect("Failed to create service account");
|
|
||||||
|
|
||||||
let gte = GenerateApiTokenEvent::new_internal(testaccount_uuid, "TestToken", Some(exp));
|
|
||||||
|
|
||||||
let api_token = idms_prox_write
|
|
||||||
.service_account_generate_api_token(>e, ct)
|
|
||||||
.expect("failed to generate new api token");
|
|
||||||
|
|
||||||
trace!(?api_token);
|
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// Now trigger 5 -> 6
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_apply_domain_migration(DOMAIN_LEVEL_6)
|
|
||||||
.expect("Unable to set domain level to version 6");
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// Now check our api token still validates.
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
|
|
||||||
// Check a new token is domain key signed.
|
|
||||||
let gte = GenerateApiTokenEvent::new_internal(testaccount_uuid, "TestToken", Some(exp));
|
|
||||||
|
|
||||||
let new_api_token = idms_prox_write
|
|
||||||
.service_account_generate_api_token(>e, ct)
|
|
||||||
.expect("failed to generate new api token");
|
|
||||||
|
|
||||||
assert_ne!(api_token.kid(), new_api_token.kid());
|
|
||||||
|
|
||||||
// Check that both tokens verify and work.
|
|
||||||
let _ident = idms_prox_write
|
|
||||||
.validate_client_auth_info_to_ident(api_token.clone().into(), ct)
|
|
||||||
.expect("Unable to verify old api token.");
|
|
||||||
|
|
||||||
let _ident = idms_prox_write
|
|
||||||
.validate_client_auth_info_to_ident(new_api_token.clone().into(), ct)
|
|
||||||
.expect("Unable to verify new api token.");
|
|
||||||
|
|
||||||
// The former key is now on the domain object.
|
|
||||||
let key_object = idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.get_key_providers()
|
|
||||||
.get_key_object(UUID_DOMAIN_INFO)
|
|
||||||
.expect("Unable to retrieve key object by uuid");
|
|
||||||
|
|
||||||
// Assert the former key is now in the domain key object, and now is "retained".
|
|
||||||
let former_kid = api_token.kid().unwrap().to_string();
|
|
||||||
let status = key_object
|
|
||||||
.kid_status(&former_kid)
|
|
||||||
.expect("Failed to access kid status");
|
|
||||||
assert_eq!(status, Some(KeyStatus::Retained));
|
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// Now trigger 6 -> 7
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_apply_domain_migration(DOMAIN_LEVEL_7)
|
|
||||||
.expect("Unable to set domain level to version 7");
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
|
|
||||||
// The key on the service account is removed.
|
|
||||||
let mut idms_prox_write = idms.proxy_write(ct).await;
|
|
||||||
|
|
||||||
let service_entry = idms_prox_write
|
|
||||||
.qs_write
|
|
||||||
.internal_search_uuid(testaccount_uuid)
|
|
||||||
.expect("Unable to access service account");
|
|
||||||
|
|
||||||
assert!(!service_entry.attribute_pres(Attribute::JwsEs256PrivateKey));
|
|
||||||
|
|
||||||
assert!(idms_prox_write.commit().is_ok());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3099,7 +3099,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_access_delete_protect_system_ranges() {
|
fn test_access_delete_protect_system_ranges() {
|
||||||
let ev1: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into();
|
let ev1: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into();
|
||||||
let ev1 = ev1.into_sealed_committed();
|
let ev1 = ev1.into_sealed_committed();
|
||||||
let r_set = vec![Arc::new(ev1)];
|
let r_set = vec![Arc::new(ev1)];
|
||||||
|
|
||||||
|
|
|
@ -292,6 +292,7 @@ impl<'a> KeyProvidersWriteTransaction<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{KeyProvider, KeyProvidersTransaction};
|
use super::{KeyProvider, KeyProvidersTransaction};
|
||||||
|
@ -299,85 +300,5 @@ mod tests {
|
||||||
use crate::value::KeyStatus;
|
use crate::value::KeyStatus;
|
||||||
use compact_jwt::{JwsEs256Signer, JwsSigner};
|
use compact_jwt::{JwsEs256Signer, JwsSigner};
|
||||||
|
|
||||||
#[qs_test(domain_level=DOMAIN_LEVEL_5)]
|
|
||||||
async fn test_key_provider_internal_migration(server: &QueryServer) {
|
|
||||||
let mut write_txn = server.write(duration_from_epoch_now()).await;
|
|
||||||
|
|
||||||
// Read the initial state of the domain object, including it's
|
|
||||||
// private key.
|
|
||||||
let domain_object_initial = write_txn
|
|
||||||
.internal_search_uuid(UUID_DOMAIN_INFO)
|
|
||||||
.expect("unable to access domain object");
|
|
||||||
|
|
||||||
let initial_private_es256_key = domain_object_initial
|
|
||||||
.get_ava_single_private_binary(Attribute::Es256PrivateKeyDer)
|
|
||||||
.map(|s| s.to_vec())
|
|
||||||
.expect("No private key found");
|
|
||||||
|
|
||||||
let initial_jwt_signer =
|
|
||||||
JwsEs256Signer::from_es256_der(&initial_private_es256_key).unwrap();
|
|
||||||
|
|
||||||
let former_kid = initial_jwt_signer.get_legacy_kid().to_string();
|
|
||||||
|
|
||||||
// Set the version to 6.
|
|
||||||
write_txn
|
|
||||||
.internal_apply_domain_migration(DOMAIN_LEVEL_6)
|
|
||||||
.expect("Unable to set domain level to version 6");
|
|
||||||
|
|
||||||
// The internal key provider is created from dl 5 to 6
|
|
||||||
let key_provider_object = write_txn
|
|
||||||
.internal_search_uuid(UUID_KEY_PROVIDER_INTERNAL)
|
|
||||||
.expect("Unable to find key provider entry.");
|
|
||||||
|
|
||||||
assert!(key_provider_object.attribute_equality(
|
|
||||||
Attribute::Name,
|
|
||||||
&PartialValue::new_iname("key_provider_internal")
|
|
||||||
));
|
|
||||||
|
|
||||||
// Check that is loaded in the qs.
|
|
||||||
let key_provider = write_txn
|
|
||||||
.get_key_providers()
|
|
||||||
.get_uuid(UUID_KEY_PROVIDER_INTERNAL)
|
|
||||||
.expect("Unable to access key provider object.");
|
|
||||||
|
|
||||||
// Because there is only one variant today ...
|
|
||||||
#[allow(irrefutable_let_patterns)]
|
|
||||||
let KeyProvider::Internal(key_provider_internal) = key_provider
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run the providers internal test
|
|
||||||
assert!(key_provider_internal.test().is_ok());
|
|
||||||
|
|
||||||
// Now at this point, the domain object should now be a key object, and have it's
|
|
||||||
// keys migrated.
|
|
||||||
let key_object = write_txn
|
|
||||||
.get_key_providers()
|
|
||||||
.get_key_object(UUID_DOMAIN_INFO)
|
|
||||||
.expect("Unable to retrieve key object by uuid");
|
|
||||||
|
|
||||||
// Assert the former key is now in the domain key object, and now is "retained".
|
|
||||||
let status = key_object
|
|
||||||
.kid_status(&former_kid)
|
|
||||||
.expect("Failed to access kid status");
|
|
||||||
assert_eq!(status, Some(KeyStatus::Retained));
|
|
||||||
|
|
||||||
// Now from DL6 -> 7 the keys are actually removed.
|
|
||||||
write_txn
|
|
||||||
.internal_apply_domain_migration(DOMAIN_LEVEL_7)
|
|
||||||
.expect("Unable to set domain level to version 7");
|
|
||||||
|
|
||||||
let domain_object_migrated = write_txn
|
|
||||||
.internal_search_uuid(UUID_DOMAIN_INFO)
|
|
||||||
.expect("unable to access domain object");
|
|
||||||
|
|
||||||
assert!(!domain_object_migrated.attribute_pres(Attribute::Es256PrivateKeyDer));
|
|
||||||
|
|
||||||
assert!(!domain_object_migrated.attribute_pres(Attribute::FernetPrivateKeyStr));
|
|
||||||
|
|
||||||
assert!(!domain_object_migrated.attribute_pres(Attribute::PrivateCookieKey));
|
|
||||||
|
|
||||||
write_txn.commit().expect("Failed to commit");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::value::CredentialType;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -80,13 +79,13 @@ impl QueryServer {
|
||||||
// are created in the next phase of migrations.
|
// are created in the next phase of migrations.
|
||||||
write_txn.set_phase(ServerPhase::SchemaReady);
|
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
|
// Init idm will now set the system config version and minimum domain
|
||||||
// level if none was present
|
// level if none was present
|
||||||
write_txn.initialise_domain_info()?;
|
write_txn.initialise_domain_info()?;
|
||||||
|
|
||||||
// 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 {
|
|
||||||
// In this path because we create the dyn groups they are immediately added to the
|
// In this path because we create the dyn groups they are immediately added to the
|
||||||
// dyngroup cache and begin to operate.
|
// dyngroup cache and begin to operate.
|
||||||
write_txn.initialise_idm()?;
|
write_txn.initialise_idm()?;
|
||||||
|
@ -294,273 +293,6 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all)]
|
|
||||||
/// This migration will
|
|
||||||
/// * Trigger a "once off" mfa account policy rule on all persons.
|
|
||||||
pub(crate) fn migrate_domain_2_to_3(&mut self) -> Result<(), OperationError> {
|
|
||||||
let idm_all_persons = match self.internal_search_uuid(UUID_IDM_ALL_PERSONS) {
|
|
||||||
Ok(entry) => entry,
|
|
||||||
Err(OperationError::NoMatchingEntries) => return Ok(()),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let credential_policy =
|
|
||||||
idm_all_persons.get_ava_single_credential_type(Attribute::CredentialTypeMinimum);
|
|
||||||
|
|
||||||
if credential_policy.is_some() {
|
|
||||||
debug!("Credential policy already present, not applying change.");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.internal_modify_uuid(
|
|
||||||
UUID_IDM_ALL_PERSONS,
|
|
||||||
&ModifyList::new_purge_and_set(
|
|
||||||
Attribute::CredentialTypeMinimum,
|
|
||||||
CredentialType::Mfa.into(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map(|()| {
|
|
||||||
info!("Upgraded default account policy to enforce MFA");
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all)]
|
|
||||||
/// Migrations for Oauth to support multiple origins, and custom claims.
|
|
||||||
pub(crate) fn migrate_domain_3_to_4(&mut self) -> Result<(), OperationError> {
|
|
||||||
let idm_schema_attrs = [
|
|
||||||
SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(),
|
|
||||||
SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4
|
|
||||||
.clone()
|
|
||||||
.into(),
|
|
||||||
];
|
|
||||||
|
|
||||||
idm_schema_attrs
|
|
||||||
.into_iter()
|
|
||||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_3_to_4 -> Error");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let idm_schema_classes = [
|
|
||||||
SCHEMA_CLASS_OAUTH2_RS_DL4.clone().into(),
|
|
||||||
SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(),
|
|
||||||
IDM_ACP_OAUTH2_MANAGE_DL4.clone().into(),
|
|
||||||
];
|
|
||||||
|
|
||||||
idm_schema_classes
|
|
||||||
.into_iter()
|
|
||||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_3_to_4 -> Error");
|
|
||||||
err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all)]
|
|
||||||
/// Migrations for Oauth to move rs name from a dedicated type to name
|
|
||||||
/// and to allow oauth2 sessions on resource servers for client credentials
|
|
||||||
/// grants. Accounts, persons and service accounts have some attributes
|
|
||||||
/// relocated to allow oauth2 rs to become accounts.
|
|
||||||
pub(crate) fn migrate_domain_4_to_5(&mut self) -> Result<(), OperationError> {
|
|
||||||
let idm_schema_classes = [
|
|
||||||
SCHEMA_CLASS_PERSON_DL5.clone().into(),
|
|
||||||
SCHEMA_CLASS_ACCOUNT_DL5.clone().into(),
|
|
||||||
SCHEMA_CLASS_SERVICE_ACCOUNT_DL5.clone().into(),
|
|
||||||
SCHEMA_CLASS_OAUTH2_RS_DL5.clone().into(),
|
|
||||||
SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(),
|
|
||||||
IDM_ACP_OAUTH2_MANAGE_DL5.clone().into(),
|
|
||||||
];
|
|
||||||
|
|
||||||
idm_schema_classes
|
|
||||||
.into_iter()
|
|
||||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_4_to_5 -> Error");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Reload mid txn so that the next modification works.
|
|
||||||
self.force_schema_reload();
|
|
||||||
self.reload()?;
|
|
||||||
|
|
||||||
// Now we remove attributes from service accounts that have been unable to be set
|
|
||||||
// via a user interface for more than a year.
|
|
||||||
let filter = filter!(f_and!([
|
|
||||||
f_eq(Attribute::Class, EntryClass::Account.into()),
|
|
||||||
f_eq(Attribute::Class, EntryClass::ServiceAccount.into()),
|
|
||||||
]));
|
|
||||||
let modlist = ModifyList::new_list(vec![
|
|
||||||
Modify::Purged(Attribute::PassKeys.into()),
|
|
||||||
Modify::Purged(Attribute::AttestedPasskeys.into()),
|
|
||||||
Modify::Purged(Attribute::CredentialUpdateIntentToken.into()),
|
|
||||||
Modify::Purged(Attribute::RadiusSecret.into()),
|
|
||||||
]);
|
|
||||||
self.internal_modify(&filter, &modlist)?;
|
|
||||||
|
|
||||||
// Now move all oauth2 rs name.
|
|
||||||
let filter = filter!(f_and!([
|
|
||||||
f_eq(Attribute::Class, EntryClass::OAuth2ResourceServer.into()),
|
|
||||||
f_pres(Attribute::OAuth2RsName),
|
|
||||||
]));
|
|
||||||
|
|
||||||
let pre_candidates = self.internal_search(filter).map_err(|err| {
|
|
||||||
admin_error!(?err, "migrate_domain_4_to_5 internal search failure");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let modset: Vec<_> = pre_candidates
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|ent| {
|
|
||||||
ent.get_ava_single_iname(Attribute::OAuth2RsName)
|
|
||||||
.map(|rs_name| {
|
|
||||||
let modlist = vec![
|
|
||||||
Modify::Present(Attribute::Class.into(), EntryClass::Account.into()),
|
|
||||||
Modify::Present(Attribute::Name.into(), Value::new_iname(rs_name)),
|
|
||||||
m_purge(Attribute::OAuth2RsName),
|
|
||||||
];
|
|
||||||
|
|
||||||
(ent.get_uuid(), ModifyList::new_list(modlist))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// If there is nothing, we don't need to do anything.
|
|
||||||
if modset.is_empty() {
|
|
||||||
admin_info!("migrate_domain_4_to_5 no entries to migrate, complete");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the batch mod.
|
|
||||||
self.internal_batch_modify(modset.into_iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Migration domain level 5 to 6 - support query limits in account policy.
|
|
||||||
#[instrument(level = "info", skip_all)]
|
|
||||||
pub(crate) fn migrate_domain_5_to_6(&mut self) -> Result<(), OperationError> {
|
|
||||||
let idm_schema_classes = [
|
|
||||||
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(),
|
|
||||||
SCHEMA_CLASS_ACCOUNT_POLICY_DL6.clone().into(),
|
|
||||||
SCHEMA_CLASS_DOMAIN_INFO_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(),
|
|
||||||
];
|
|
||||||
|
|
||||||
idm_schema_classes
|
|
||||||
.into_iter()
|
|
||||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_5_to_6 -> Error");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
self.reload()?;
|
|
||||||
|
|
||||||
let idm_data = [
|
|
||||||
// Update access controls.
|
|
||||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone().into(),
|
|
||||||
IDM_ACP_PEOPLE_CREATE_DL6.clone().into(),
|
|
||||||
IDM_ACP_GROUP_MANAGE_DL6.clone().into(),
|
|
||||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(),
|
|
||||||
// Update anonymous with the correct entry manager,
|
|
||||||
BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(),
|
|
||||||
// Add the internal key provider.
|
|
||||||
E_KEY_PROVIDER_INTERNAL_DL6.clone(),
|
|
||||||
];
|
|
||||||
|
|
||||||
idm_data
|
|
||||||
.into_iter()
|
|
||||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_5_to_6 -> Error");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// all existing built-in objects get a builtin class
|
|
||||||
let filter = f_lt(
|
|
||||||
Attribute::Uuid,
|
|
||||||
PartialValue::Uuid(DYNAMIC_RANGE_MINIMUM_UUID),
|
|
||||||
);
|
|
||||||
let modlist = modlist!([m_pres(Attribute::Class, &EntryClass::Builtin.into())]);
|
|
||||||
|
|
||||||
self.internal_modify(&filter!(filter), &modlist)?;
|
|
||||||
|
|
||||||
// Reload such that the new default key provider is loaded.
|
|
||||||
self.reload()?;
|
|
||||||
|
|
||||||
// Update the domain entry to contain its key object, which can now be generated.
|
|
||||||
let idm_data = [
|
|
||||||
IDM_ACP_DOMAIN_ADMIN_DL6.clone().into(),
|
|
||||||
E_DOMAIN_INFO_DL6.clone(),
|
|
||||||
];
|
|
||||||
idm_data
|
|
||||||
.into_iter()
|
|
||||||
.try_for_each(|entry| self.internal_migrate_or_create(entry))
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_5_to_6 -> Error");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// At this point we reload to show the new key objects on the domain.
|
|
||||||
self.reload()?;
|
|
||||||
|
|
||||||
// Migrate the domain key to a retained key on the key object.
|
|
||||||
let domain_es256_private_key = self.get_domain_es256_private_key().map_err(|err| {
|
|
||||||
error!(?err, "migrate_domain_5_to_6 -> Error");
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Migrate all service/scim account keys to the domain key for verification.
|
|
||||||
let filter = filter!(f_or!([
|
|
||||||
f_eq(Attribute::Class, EntryClass::ServiceAccount.into()),
|
|
||||||
f_eq(Attribute::Class, EntryClass::SyncAccount.into())
|
|
||||||
]));
|
|
||||||
let entry_keys_to_migrate = self.internal_search(filter)?;
|
|
||||||
|
|
||||||
let mut modlist = Vec::with_capacity(1 + entry_keys_to_migrate.len());
|
|
||||||
|
|
||||||
modlist.push(Modify::Present(
|
|
||||||
Attribute::KeyActionImportJwsEs256.into(),
|
|
||||||
Value::PrivateBinary(domain_es256_private_key),
|
|
||||||
));
|
|
||||||
|
|
||||||
for entry in entry_keys_to_migrate {
|
|
||||||
// In these entries, the keys are in JwsEs256PrivateKey.
|
|
||||||
if let Some(jws_signer) =
|
|
||||||
entry.get_ava_single_jws_key_es256(Attribute::JwsEs256PrivateKey)
|
|
||||||
{
|
|
||||||
let es256_private_key = jws_signer.private_key_to_der().map_err(|err| {
|
|
||||||
error!(?err, uuid = ?entry.get_display_id(), "unable to convert signer to der");
|
|
||||||
OperationError::InvalidValueState
|
|
||||||
})?;
|
|
||||||
|
|
||||||
modlist.push(Modify::Present(
|
|
||||||
Attribute::KeyActionImportJwsEs256.into(),
|
|
||||||
Value::PrivateBinary(es256_private_key),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let modlist = ModifyList::new_list(modlist);
|
|
||||||
|
|
||||||
self.internal_modify_uuid(UUID_DOMAIN_INFO, &modlist)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Migration domain level 6 to 7
|
/// Migration domain level 6 to 7
|
||||||
#[instrument(level = "info", skip_all)]
|
#[instrument(level = "info", skip_all)]
|
||||||
pub(crate) fn migrate_domain_6_to_7(&mut self) -> Result<(), OperationError> {
|
pub(crate) fn migrate_domain_6_to_7(&mut self) -> Result<(), OperationError> {
|
||||||
|
@ -859,6 +591,19 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Migration domain level 8 to 9
|
||||||
|
#[instrument(level = "info", skip_all)]
|
||||||
|
pub(crate) fn migrate_domain_8_to_9(&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 ==============
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all)]
|
#[instrument(level = "info", skip_all)]
|
||||||
pub fn initialise_schema_core(&mut self) -> Result<(), OperationError> {
|
pub fn initialise_schema_core(&mut self) -> Result<(), OperationError> {
|
||||||
admin_debug!("initialise_schema_core -> start ...");
|
admin_debug!("initialise_schema_core -> start ...");
|
||||||
|
@ -966,6 +711,20 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
SCHEMA_ATTR_DENIED_NAME.clone().into(),
|
SCHEMA_ATTR_DENIED_NAME.clone().into(),
|
||||||
SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(),
|
SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(),
|
||||||
SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.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(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let r = idm_schema
|
let r = idm_schema
|
||||||
|
@ -984,21 +743,30 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
//
|
//
|
||||||
// DO NOT MODIFY THIS DEFINITION
|
// DO NOT MODIFY THIS DEFINITION
|
||||||
let idm_schema_classes_dl1: Vec<EntryInitNew> = vec![
|
let idm_schema_classes_dl1: Vec<EntryInitNew> = vec![
|
||||||
SCHEMA_CLASS_ACCOUNT.clone().into(),
|
|
||||||
SCHEMA_CLASS_ACCOUNT_POLICY.clone().into(),
|
|
||||||
SCHEMA_CLASS_DOMAIN_INFO.clone().into(),
|
|
||||||
SCHEMA_CLASS_DYNGROUP.clone().into(),
|
SCHEMA_CLASS_DYNGROUP.clone().into(),
|
||||||
SCHEMA_CLASS_GROUP.clone().into(),
|
|
||||||
SCHEMA_CLASS_OAUTH2_RS.clone().into(),
|
|
||||||
SCHEMA_CLASS_ORGPERSON.clone().into(),
|
SCHEMA_CLASS_ORGPERSON.clone().into(),
|
||||||
SCHEMA_CLASS_PERSON.clone().into(),
|
|
||||||
SCHEMA_CLASS_POSIXACCOUNT.clone().into(),
|
SCHEMA_CLASS_POSIXACCOUNT.clone().into(),
|
||||||
SCHEMA_CLASS_POSIXGROUP.clone().into(),
|
SCHEMA_CLASS_POSIXGROUP.clone().into(),
|
||||||
SCHEMA_CLASS_SERVICE_ACCOUNT.clone().into(),
|
|
||||||
SCHEMA_CLASS_SYNC_ACCOUNT.clone().into(),
|
|
||||||
SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(),
|
SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(),
|
||||||
SCHEMA_CLASS_OAUTH2_RS_BASIC.clone().into(),
|
// DL4
|
||||||
SCHEMA_CLASS_OAUTH2_RS_PUBLIC.clone().into(),
|
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_DOMAIN_INFO_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(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let r: Result<(), _> = idm_schema_classes_dl1
|
let r: Result<(), _> = idm_schema_classes_dl1
|
||||||
|
@ -1018,18 +786,24 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
#[instrument(level = "info", skip_all)]
|
#[instrument(level = "info", skip_all)]
|
||||||
/// This function is idempotent, runs all the startup functionality and checks
|
/// This function is idempotent, runs all the startup functionality and checks
|
||||||
pub fn initialise_domain_info(&mut self) -> Result<(), OperationError> {
|
pub fn initialise_domain_info(&mut self) -> Result<(), OperationError> {
|
||||||
// First, check the system_info object. This stores some server information
|
// Configure the default key provider. This needs to exist *before* the
|
||||||
// and details. It's a pretty const thing. Also check anonymous, important to many
|
// domain info!
|
||||||
// concepts.
|
self.internal_migrate_or_create(E_KEY_PROVIDER_INTERNAL_DL6.clone())
|
||||||
let res = self
|
.and_then(|_| self.reload())
|
||||||
.internal_migrate_or_create(E_SYSTEM_INFO_V1.clone())
|
.map_err(|err| {
|
||||||
.and_then(|_| self.internal_migrate_or_create(E_DOMAIN_INFO_V1.clone()))
|
error!(?err, "initialise_domain_info::E_KEY_PROVIDER_INTERNAL_DL6");
|
||||||
.and_then(|_| self.internal_migrate_or_create(E_SYSTEM_CONFIG_V1.clone()));
|
debug_assert!(false);
|
||||||
if res.is_err() {
|
err
|
||||||
admin_error!("initialise_domain_info -> result {:?}", res);
|
})?;
|
||||||
}
|
|
||||||
debug_assert!(res.is_ok());
|
self.internal_migrate_or_create(E_SYSTEM_INFO_V1.clone())
|
||||||
res
|
.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)]
|
#[instrument(level = "info", skip_all)]
|
||||||
|
@ -1048,9 +822,9 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
// Each item individually logs it's result
|
// Each item individually logs it's result
|
||||||
.try_for_each(|ent| self.internal_migrate_or_create(ent));
|
.try_for_each(|ent| self.internal_migrate_or_create(ent));
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
admin_debug!("initialise_idm p1 -> result Ok!");
|
debug!("initialise_idm p1 -> result Ok!");
|
||||||
} else {
|
} else {
|
||||||
admin_error!(?res, "initialise_idm p1 -> result");
|
error!(?res, "initialise_idm p1 -> result");
|
||||||
}
|
}
|
||||||
debug_assert!(res.is_ok());
|
debug_assert!(res.is_ok());
|
||||||
res?;
|
res?;
|
||||||
|
@ -1059,9 +833,9 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|e| self.internal_migrate_or_create(e.clone().try_into()?));
|
.try_for_each(|e| self.internal_migrate_or_create(e.clone().try_into()?));
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
admin_debug!("initialise_idm p2 -> result Ok!");
|
debug!("initialise_idm p2 -> result Ok!");
|
||||||
} else {
|
} else {
|
||||||
admin_error!(?res, "initialise_idm p2 -> result");
|
error!(?res, "initialise_idm p2 -> result");
|
||||||
}
|
}
|
||||||
debug_assert!(res.is_ok());
|
debug_assert!(res.is_ok());
|
||||||
res?;
|
res?;
|
||||||
|
@ -1079,9 +853,6 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
IDM_ACP_ACP_MANAGE_V1.clone(),
|
IDM_ACP_ACP_MANAGE_V1.clone(),
|
||||||
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone(),
|
IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone(),
|
||||||
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone(),
|
IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone(),
|
||||||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_V1.clone(),
|
|
||||||
IDM_ACP_OAUTH2_MANAGE_V1.clone(),
|
|
||||||
IDM_ACP_DOMAIN_ADMIN_V1.clone(),
|
|
||||||
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone(),
|
IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone(),
|
||||||
IDM_ACP_RADIUS_SERVERS_V1.clone(),
|
IDM_ACP_RADIUS_SERVERS_V1.clone(),
|
||||||
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone(),
|
IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone(),
|
||||||
|
@ -1091,16 +862,13 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone(),
|
IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone(),
|
||||||
IDM_ACP_SELF_NAME_WRITE_V1.clone(),
|
IDM_ACP_SELF_NAME_WRITE_V1.clone(),
|
||||||
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone(),
|
IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone(),
|
||||||
IDM_ACP_ACCOUNT_MAIL_READ_V1.clone(),
|
|
||||||
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1.clone(),
|
IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1.clone(),
|
||||||
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone(),
|
IDM_ACP_GROUP_UNIX_MANAGE_V1.clone(),
|
||||||
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone(),
|
IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone(),
|
||||||
IDM_ACP_GROUP_READ_V1.clone(),
|
IDM_ACP_GROUP_READ_V1.clone(),
|
||||||
IDM_ACP_GROUP_MANAGE_V1.clone(),
|
|
||||||
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone(),
|
IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone(),
|
||||||
IDM_ACP_PEOPLE_PII_READ_V1.clone(),
|
IDM_ACP_PEOPLE_PII_READ_V1.clone(),
|
||||||
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone(),
|
IDM_ACP_PEOPLE_PII_MANAGE_V1.clone(),
|
||||||
IDM_ACP_PEOPLE_CREATE_V1.clone(),
|
|
||||||
IDM_ACP_PEOPLE_READ_V1.clone(),
|
IDM_ACP_PEOPLE_READ_V1.clone(),
|
||||||
IDM_ACP_PEOPLE_MANAGE_V1.clone(),
|
IDM_ACP_PEOPLE_MANAGE_V1.clone(),
|
||||||
IDM_ACP_PEOPLE_DELETE_V1.clone(),
|
IDM_ACP_PEOPLE_DELETE_V1.clone(),
|
||||||
|
@ -1112,6 +880,15 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_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_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1.clone(),
|
||||||
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone(),
|
IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone(),
|
||||||
|
// DL4
|
||||||
|
// DL5
|
||||||
|
IDM_ACP_OAUTH2_MANAGE_DL5.clone().into(),
|
||||||
|
// DL6
|
||||||
|
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone().into(),
|
||||||
|
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(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let res: Result<(), _> = idm_entries
|
let res: Result<(), _> = idm_entries
|
||||||
|
@ -1375,46 +1152,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[qs_test(domain_level=DOMAIN_LEVEL_5)]
|
|
||||||
async fn test_migrations_dl5_dl6(server: &QueryServer) {
|
|
||||||
// Assert our instance was setup to version 5
|
|
||||||
let mut write_txn = server.write(duration_from_epoch_now()).await;
|
|
||||||
|
|
||||||
let db_domain_version = write_txn
|
|
||||||
.internal_search_uuid(UUID_DOMAIN_INFO)
|
|
||||||
.expect("unable to access domain entry")
|
|
||||||
.get_ava_single_uint32(Attribute::Version)
|
|
||||||
.expect("Attribute Version not present");
|
|
||||||
|
|
||||||
assert_eq!(db_domain_version, DOMAIN_LEVEL_5);
|
|
||||||
|
|
||||||
// Entry doesn't exist yet.
|
|
||||||
let _entry_not_found = write_txn
|
|
||||||
.internal_search_uuid(UUID_SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS)
|
|
||||||
.expect_err("unable to newly migrated schema entry");
|
|
||||||
|
|
||||||
// Set the version to 6.
|
|
||||||
write_txn
|
|
||||||
.internal_modify_uuid(
|
|
||||||
UUID_DOMAIN_INFO,
|
|
||||||
&ModifyList::new_purge_and_set(
|
|
||||||
Attribute::Version,
|
|
||||||
Value::new_uint32(DOMAIN_LEVEL_6),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.expect("Unable to set domain level to version 6");
|
|
||||||
|
|
||||||
// Re-load - this applies the migrations.
|
|
||||||
write_txn.reload().expect("Unable to reload transaction");
|
|
||||||
|
|
||||||
// It now exists as the migrations were run.
|
|
||||||
let _entry = write_txn
|
|
||||||
.internal_search_uuid(UUID_SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS)
|
|
||||||
.expect("unable to newly migrated schema entry");
|
|
||||||
|
|
||||||
write_txn.commit().expect("Unable to commit");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[qs_test(domain_level=DOMAIN_LEVEL_6)]
|
#[qs_test(domain_level=DOMAIN_LEVEL_6)]
|
||||||
async fn test_migrations_dl6_dl7(server: &QueryServer) {
|
async fn test_migrations_dl6_dl7(server: &QueryServer) {
|
||||||
// Assert our instance was setup to version 6
|
// Assert our instance was setup to version 6
|
||||||
|
@ -1460,18 +1197,9 @@ mod tests {
|
||||||
|
|
||||||
// Set the version to 7.
|
// Set the version to 7.
|
||||||
write_txn
|
write_txn
|
||||||
.internal_modify_uuid(
|
.internal_apply_domain_migration(DOMAIN_LEVEL_7)
|
||||||
UUID_DOMAIN_INFO,
|
|
||||||
&ModifyList::new_purge_and_set(
|
|
||||||
Attribute::Version,
|
|
||||||
Value::new_uint32(DOMAIN_LEVEL_7),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.expect("Unable to set domain level to version 7");
|
.expect("Unable to set domain level to version 7");
|
||||||
|
|
||||||
// Re-load - this applies the migrations.
|
|
||||||
write_txn.reload().expect("Unable to reload transaction");
|
|
||||||
|
|
||||||
// post migration verification.
|
// post migration verification.
|
||||||
let domain_entry = write_txn
|
let domain_entry = write_txn
|
||||||
.internal_search_uuid(UUID_DOMAIN_INFO)
|
.internal_search_uuid(UUID_DOMAIN_INFO)
|
||||||
|
@ -1582,20 +1310,14 @@ mod tests {
|
||||||
|
|
||||||
// Set the version to 8.
|
// Set the version to 8.
|
||||||
write_txn
|
write_txn
|
||||||
.internal_modify_uuid(
|
.internal_apply_domain_migration(DOMAIN_LEVEL_8)
|
||||||
UUID_DOMAIN_INFO,
|
|
||||||
&ModifyList::new_purge_and_set(
|
|
||||||
Attribute::Version,
|
|
||||||
Value::new_uint32(DOMAIN_LEVEL_8),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.expect("Unable to set domain level to version 8");
|
.expect("Unable to set domain level to version 8");
|
||||||
|
|
||||||
// Re-load - this applies the migrations.
|
|
||||||
write_txn.reload().expect("Unable to reload transaction");
|
|
||||||
|
|
||||||
// post migration verification.
|
// post migration verification.
|
||||||
|
|
||||||
write_txn.commit().expect("Unable to commit");
|
write_txn.commit().expect("Unable to commit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[qs_test(domain_level=DOMAIN_LEVEL_8)]
|
||||||
|
async fn test_migrations_dl8_dl9(_server: &QueryServer) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1890,20 +1890,13 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
debug!(domain_previous_version = ?previous_version, domain_target_version = ?domain_info_version);
|
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);
|
debug!(domain_previous_patch_level = ?previous_patch_level, domain_target_patch_level = ?domain_info_patch_level);
|
||||||
|
|
||||||
if previous_version <= DOMAIN_LEVEL_2 && domain_info_version >= DOMAIN_LEVEL_3 {
|
// We have to check for DL0 since that's the initialisation level.
|
||||||
self.migrate_domain_2_to_3()?;
|
if previous_version <= DOMAIN_LEVEL_5 && previous_version != DOMAIN_LEVEL_0 {
|
||||||
}
|
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");
|
||||||
if previous_version <= DOMAIN_LEVEL_3 && domain_info_version >= DOMAIN_LEVEL_4 {
|
error!(domain_previous_version = ?previous_version, domain_target_version = ?domain_info_version);
|
||||||
self.migrate_domain_3_to_4()?;
|
error!(domain_previous_patch_level = ?previous_patch_level, domain_target_patch_level = ?domain_info_patch_level);
|
||||||
}
|
return Err(OperationError::MG0008SkipUpgradeAttempted);
|
||||||
|
|
||||||
if previous_version <= DOMAIN_LEVEL_4 && domain_info_version >= DOMAIN_LEVEL_5 {
|
|
||||||
self.migrate_domain_4_to_5()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if previous_version <= DOMAIN_LEVEL_5 && domain_info_version >= DOMAIN_LEVEL_6 {
|
|
||||||
self.migrate_domain_5_to_6()?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if previous_version <= DOMAIN_LEVEL_6 && domain_info_version >= DOMAIN_LEVEL_7 {
|
if previous_version <= DOMAIN_LEVEL_6 && domain_info_version >= DOMAIN_LEVEL_7 {
|
||||||
|
@ -1920,6 +1913,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
self.migrate_domain_7_to_8()?;
|
self.migrate_domain_7_to_8()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if previous_version <= DOMAIN_LEVEL_8 && domain_info_version >= DOMAIN_LEVEL_9 {
|
||||||
|
self.migrate_domain_8_to_9()?;
|
||||||
|
}
|
||||||
|
|
||||||
// This is here to catch when we increase domain levels but didn't create the migration
|
// 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
|
// hooks. If this fails it probably means you need to add another migration hook
|
||||||
// in the above.
|
// in the above.
|
||||||
|
|
|
@ -48,6 +48,7 @@ const TEST_INTEGRATION_RS_ID: &str = "test_integration";
|
||||||
const TEST_INTEGRATION_RS_GROUP_ALL: &str = "idm_all_accounts";
|
const TEST_INTEGRATION_RS_GROUP_ALL: &str = "idm_all_accounts";
|
||||||
const TEST_INTEGRATION_RS_DISPLAY: &str = "Test Integration";
|
const TEST_INTEGRATION_RS_DISPLAY: &str = "Test Integration";
|
||||||
const TEST_INTEGRATION_RS_URL: &str = "https://demo.example.com";
|
const TEST_INTEGRATION_RS_URL: &str = "https://demo.example.com";
|
||||||
|
const TEST_INTEGRATION_REDIRECT_URL: &str = "https://demo.example.com/oauth2/flow";
|
||||||
|
|
||||||
#[kanidmd_testkit::test]
|
#[kanidmd_testkit::test]
|
||||||
async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
||||||
|
@ -66,6 +67,14 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create oauth2 config");
|
.expect("Failed to create oauth2 config");
|
||||||
|
|
||||||
|
rsclient
|
||||||
|
.idm_oauth2_client_add_origin(
|
||||||
|
TEST_INTEGRATION_RS_ID,
|
||||||
|
&Url::parse(TEST_INTEGRATION_REDIRECT_URL).expect("Invalid URL"),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Failed to update oauth2 config");
|
||||||
|
|
||||||
// Extend the admin account with extended details for openid claims.
|
// Extend the admin account with extended details for openid claims.
|
||||||
rsclient
|
rsclient
|
||||||
.idm_person_account_create("oauth_test", "oauth_test")
|
.idm_person_account_create("oauth_test", "oauth_test")
|
||||||
|
@ -236,7 +245,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
||||||
("state", "YWJjZGVm"),
|
("state", "YWJjZGVm"),
|
||||||
("code_challenge", pkce_code_challenge.as_str()),
|
("code_challenge", pkce_code_challenge.as_str()),
|
||||||
("code_challenge_method", "S256"),
|
("code_challenge_method", "S256"),
|
||||||
("redirect_uri", "https://demo.example.com/oauth2/flow"),
|
("redirect_uri", TEST_INTEGRATION_REDIRECT_URL),
|
||||||
("scope", "email read openid"),
|
("scope", "email read openid"),
|
||||||
])
|
])
|
||||||
.send()
|
.send()
|
||||||
|
@ -303,7 +312,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
||||||
|
|
||||||
let form_req: AccessTokenRequest = GrantTypeReq::AuthorizationCode {
|
let form_req: AccessTokenRequest = GrantTypeReq::AuthorizationCode {
|
||||||
code: code.to_string(),
|
code: code.to_string(),
|
||||||
redirect_uri: Url::parse("https://demo.example.com/oauth2/flow").expect("Invalid URL"),
|
redirect_uri: Url::parse(TEST_INTEGRATION_REDIRECT_URL).expect("Invalid URL"),
|
||||||
code_verifier: Some(pkce_code_verifier.secret().clone()),
|
code_verifier: Some(pkce_code_verifier.secret().clone()),
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
|
@ -496,6 +505,14 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create oauth2 config");
|
.expect("Failed to create oauth2 config");
|
||||||
|
|
||||||
|
rsclient
|
||||||
|
.idm_oauth2_client_add_origin(
|
||||||
|
TEST_INTEGRATION_RS_ID,
|
||||||
|
&Url::parse(TEST_INTEGRATION_REDIRECT_URL).expect("Invalid URL"),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Failed to update oauth2 config");
|
||||||
|
|
||||||
// Extend the admin account with extended details for openid claims.
|
// Extend the admin account with extended details for openid claims.
|
||||||
rsclient
|
rsclient
|
||||||
.idm_person_account_create("oauth_test", "oauth_test")
|
.idm_person_account_create("oauth_test", "oauth_test")
|
||||||
|
@ -616,7 +633,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
|
||||||
("state", "YWJjZGVm"),
|
("state", "YWJjZGVm"),
|
||||||
("code_challenge", pkce_code_challenge.as_str()),
|
("code_challenge", pkce_code_challenge.as_str()),
|
||||||
("code_challenge_method", "S256"),
|
("code_challenge_method", "S256"),
|
||||||
("redirect_uri", "https://demo.example.com/oauth2/flow"),
|
("redirect_uri", TEST_INTEGRATION_REDIRECT_URL),
|
||||||
("scope", "email read openid"),
|
("scope", "email read openid"),
|
||||||
])
|
])
|
||||||
.send()
|
.send()
|
||||||
|
@ -683,7 +700,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
|
||||||
let form_req = AccessTokenRequest {
|
let form_req = AccessTokenRequest {
|
||||||
grant_type: GrantTypeReq::AuthorizationCode {
|
grant_type: GrantTypeReq::AuthorizationCode {
|
||||||
code: code.to_string(),
|
code: code.to_string(),
|
||||||
redirect_uri: Url::parse("https://demo.example.com/oauth2/flow").expect("Invalid URL"),
|
redirect_uri: Url::parse(TEST_INTEGRATION_REDIRECT_URL).expect("Invalid URL"),
|
||||||
code_verifier: Some(pkce_code_verifier.secret().clone()),
|
code_verifier: Some(pkce_code_verifier.secret().clone()),
|
||||||
},
|
},
|
||||||
client_id: Some("test_integration".to_string()),
|
client_id: Some("test_integration".to_string()),
|
||||||
|
|
Loading…
Reference in a new issue