From cb287eeb61bd22c406c0f9745843bd79164d2f52 Mon Sep 17 00:00:00 2001 From: William Brown Date: Thu, 13 Feb 2025 13:15:22 +1000 Subject: [PATCH] Major refactor of migrations to improve durability. Migrations and server bootstrap are very interconnected processes and in this we'll be addressing and improving both. Server bootstrap was performed by creating base entries in phases, eventually bringing up enough of the *oldest* supported server minimum remigration level, to then allow triggering of migrations. Migrations then applied "patches" effectively ontop of this minimum level to update entries to what they should be in newer versions of the server. This scheme has it's pros and cons, but the major con was that to remove a migration meant squashing it's content back into the minimum remigration level, and this was a human process that was quite error prone and difficult to automate. As well, this scheme also led to cases where the patch migrations would sometimes *not* reflect all the needed changes or content, or in one case was actually undone by a patchlevel fix up that was required to address a bug. Invariably this led to issues, and cases where a new server may have different content to a migrated one - not exactly what we want! This is a new migration scheme that addresses this fragility. However what it trades is verbosity of the content. Rather than having a base set of entries and patching/updating small sections ontop, we have migration data folders that contain the full set of entries as they should appear at that migration level. This makes the bootstrap process easier as we can just apply the migration level as a whole, and targetted to what precise version we want. This also makes migrations more durable as the content is explicitly copied and all entries fully applied, so there is no risk that a migration or data change can be forgotten or applied incorrectly. We are expressing the full state of what our builtin and provided entries should be. Finally this rips out a number of places where migration data was being used as test case data. Not all of these have been replaced (notably in authsession with Account), but the majority have and have been replaced with clearer use of constants rather than building whole entries just to access the name and throw them away for example. --- proto/src/internal/error.rs | 2 + server/lib/src/constants/entries.rs | 191 +- server/lib/src/constants/mod.rs | 10 - server/lib/src/constants/uuids.rs | 10 + server/lib/src/event.rs | 17 - server/lib/src/idm/account.rs | 8 - server/lib/src/idm/authsession.rs | 21 +- server/lib/src/idm/ldap.rs | 2 +- server/lib/src/lib.rs | 6 + .../acp.rs => migration_data/dl10/access.rs} | 0 .../lib/src/migration_data/dl10/accounts.rs | 35 + server/lib/src/migration_data/dl10/groups.rs | 408 +++ .../dl10}/key_providers.rs | 0 server/lib/src/migration_data/dl10/mod.rs | 268 ++ .../dl10}/schema.rs | 5 +- .../dl10}/system_config.rs | 25 + server/lib/src/migration_data/dl8/access.rs | 2637 +++++++++++++++++ server/lib/src/migration_data/dl8/accounts.rs | 35 + .../dl8}/groups.rs | 45 +- .../src/migration_data/dl8/key_providers.rs | 18 + server/lib/src/migration_data/dl8/mod.rs | 273 ++ server/lib/src/migration_data/dl8/schema.rs | 1506 ++++++++++ .../src/migration_data/dl8/system_config.rs | 1073 +++++++ server/lib/src/migration_data/dl9/access.rs | 2637 +++++++++++++++++ server/lib/src/migration_data/dl9/accounts.rs | 35 + server/lib/src/migration_data/dl9/groups.rs | 408 +++ .../src/migration_data/dl9/key_providers.rs | 18 + server/lib/src/migration_data/dl9/mod.rs | 264 ++ server/lib/src/migration_data/dl9/schema.rs | 1506 ++++++++++ .../src/migration_data/dl9/system_config.rs | 1073 +++++++ server/lib/src/migration_data/mod.rs | 24 + server/lib/src/migration_data/types.rs | 83 + server/lib/src/server/access/mod.rs | 6 +- server/lib/src/server/migrations.rs | 683 ++--- server/lib/src/server/mod.rs | 23 +- server/lib/src/server/modify.rs | 6 +- .../enumerating_access.rs | 8 +- server/testkit/src/lib.rs | 4 +- server/testkit/tests/oauth2_device_flow.rs | 11 +- server/testkit/tests/oauth2_test.rs | 13 +- server/testkit/tests/proto_v1_test.rs | 57 +- server/testkit/tests/scim_test.rs | 5 +- server/testkit/tests/unix.rs | 9 +- 43 files changed, 12670 insertions(+), 798 deletions(-) rename server/lib/src/{constants/acp.rs => migration_data/dl10/access.rs} (100%) create mode 100644 server/lib/src/migration_data/dl10/accounts.rs create mode 100644 server/lib/src/migration_data/dl10/groups.rs rename server/lib/src/{constants => migration_data/dl10}/key_providers.rs (100%) create mode 100644 server/lib/src/migration_data/dl10/mod.rs rename server/lib/src/{constants => migration_data/dl10}/schema.rs (99%) rename server/lib/src/{constants => migration_data/dl10}/system_config.rs (97%) create mode 100644 server/lib/src/migration_data/dl8/access.rs create mode 100644 server/lib/src/migration_data/dl8/accounts.rs rename server/lib/src/{constants => migration_data/dl8}/groups.rs (90%) create mode 100644 server/lib/src/migration_data/dl8/key_providers.rs create mode 100644 server/lib/src/migration_data/dl8/mod.rs create mode 100644 server/lib/src/migration_data/dl8/schema.rs create mode 100644 server/lib/src/migration_data/dl8/system_config.rs create mode 100644 server/lib/src/migration_data/dl9/access.rs create mode 100644 server/lib/src/migration_data/dl9/accounts.rs create mode 100644 server/lib/src/migration_data/dl9/groups.rs create mode 100644 server/lib/src/migration_data/dl9/key_providers.rs create mode 100644 server/lib/src/migration_data/dl9/mod.rs create mode 100644 server/lib/src/migration_data/dl9/schema.rs create mode 100644 server/lib/src/migration_data/dl9/system_config.rs create mode 100644 server/lib/src/migration_data/mod.rs create mode 100644 server/lib/src/migration_data/types.rs rename server/testkit/{examples => defunct_examples}/enumerating_access.rs (94%) diff --git a/proto/src/internal/error.rs b/proto/src/internal/error.rs index 0c3076876..09f6cb144 100644 --- a/proto/src/internal/error.rs +++ b/proto/src/internal/error.rs @@ -222,6 +222,7 @@ pub enum OperationError { MG0006SKConstraintsNotMet, MG0007Oauth2StrictConstraintsNotMet, MG0008SkipUpgradeAttempted, + MG0009InvalidTargetLevelForBootstrap, // KP0001KeyProviderNotLoaded, KP0002KeyProviderInvalidClass, @@ -462,6 +463,7 @@ impl OperationError { Self::MG0006SKConstraintsNotMet => Some("Migration Constraints Not Met - Security Keys should not be present.".into()), Self::MG0007Oauth2StrictConstraintsNotMet => Some("Migration Constraints Not Met - All OAuth2 clients must have strict-redirect-uri mode enabled.".into()), Self::MG0008SkipUpgradeAttempted => Some("Skip Upgrade Attempted.".into()), + Self::MG0009InvalidTargetLevelForBootstrap => Some("The request target domain level was not valid for bootstrapping a new server instance".into()), Self::PL0001GidOverlapsSystemRange => None, Self::SC0001IncomingSshPublicKey => None, Self::SC0002ReferenceSyntaxInvalid => Some("A SCIM Reference Set contained invalid syntax and can not be processed.".into()), diff --git a/server/lib/src/constants/entries.rs b/server/lib/src/constants/entries.rs index 753885c9c..36f48aac4 100644 --- a/server/lib/src/constants/entries.rs +++ b/server/lib/src/constants/entries.rs @@ -1,20 +1,12 @@ //! Constant Entries for the IDM use std::fmt::Display; -use crate::constants::groups::idm_builtin_admin_groups; -use crate::constants::uuids::*; -use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew}; -use crate::idm::account::Account; use crate::value::PartialValue; use crate::value::Value; use crate::valueset::{ValueSet, ValueSetIutf8}; pub use kanidm_proto::attribute::Attribute; use kanidm_proto::constants::*; -use kanidm_proto::internal::OperationError; use kanidm_proto::scim_v1::JsonValue; -use kanidm_proto::v1::AccountType; - -use uuid::Uuid; //TODO: This would do well in the proto lib // together with all the other definitions. @@ -202,158 +194,9 @@ impl EntryClass { } } -lazy_static! { - /// Builtin System Admin account. - pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount { - account_type: AccountType::ServiceAccount, - entry_managed_by: None, - name: "idm_admin", - uuid: UUID_IDM_ADMIN, - description: "Builtin IDM Admin account.", - displayname: "IDM Administrator", - }; - - pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!( - (Attribute::Class, EntryClass::Object.to_value()), - (Attribute::Class, EntryClass::SystemInfo.to_value()), - (Attribute::Class, EntryClass::System.to_value()), - (Attribute::Uuid, Value::Uuid(UUID_SYSTEM_INFO)), - ( - Attribute::Description, - Value::new_utf8s("System (local) info and metadata object.") - ), - (Attribute::Version, Value::Uint32(20)) - ); - - pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!( - (Attribute::Class, EntryClass::Object.to_value()), - (Attribute::Class, EntryClass::DomainInfo.to_value()), - (Attribute::Class, EntryClass::System.to_value()), - (Attribute::Class, EntryClass::KeyObject.to_value()), - (Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()), - (Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()), - (Attribute::Name, Value::new_iname("domain_local")), - (Attribute::Uuid, Value::Uuid(UUID_DOMAIN_INFO)), - ( - Attribute::Description, - Value::new_utf8s("This local domain's info and metadata object.") - ) - ); -} - -#[derive(Debug, Clone)] -/// Built in accounts such as anonymous, idm_admin and admin -pub struct BuiltinAccount { - pub account_type: kanidm_proto::v1::AccountType, - pub entry_managed_by: Option, - pub name: &'static str, - pub uuid: Uuid, - pub description: &'static str, - pub displayname: &'static str, -} - -impl Default for BuiltinAccount { - fn default() -> Self { - BuiltinAccount { - account_type: AccountType::ServiceAccount, - entry_managed_by: None, - name: "", - uuid: Uuid::new_v4(), - description: "", - displayname: "", - } - } -} - -impl From for Account { - fn from(value: BuiltinAccount) -> Self { - #[allow(clippy::panic)] - if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { - panic!("Builtin ACP has invalid UUID! {:?}", value); - } - Account { - name: value.name.to_string(), - uuid: value.uuid, - displayname: value.displayname.to_string(), - spn: format!("{}@example.com", value.name), - mail_primary: None, - mail: Vec::with_capacity(0), - ..Default::default() - } - } -} - -impl From for EntryInitNew { - fn from(value: BuiltinAccount) -> Self { - let mut entry = EntryInitNew::new(); - entry.add_ava(Attribute::Name, Value::new_iname(value.name)); - #[allow(clippy::panic)] - if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { - panic!("Builtin ACP has invalid UUID! {:?}", value); - } - entry.add_ava(Attribute::Uuid, Value::Uuid(value.uuid)); - entry.add_ava(Attribute::Description, Value::new_utf8s(value.description)); - entry.add_ava(Attribute::DisplayName, Value::new_utf8s(value.displayname)); - - if let Some(entry_manager) = value.entry_managed_by { - entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager)); - } - - entry.set_ava( - Attribute::Class, - vec![ - EntryClass::Account.to_value(), - EntryClass::MemberOf.to_value(), - EntryClass::Object.to_value(), - ], - ); - match value.account_type { - AccountType::Person => entry.add_ava(Attribute::Class, EntryClass::Person.to_value()), - AccountType::ServiceAccount => { - entry.add_ava(Attribute::Class, EntryClass::ServiceAccount.to_value()) - } - } - entry - } -} - -lazy_static! { - /// Builtin System Admin account. - pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount { - account_type: AccountType::ServiceAccount, - entry_managed_by: None, - name: "admin", - uuid: UUID_ADMIN, - description: "Builtin System Admin account.", - displayname: "System Administrator", - }; -} - -lazy_static! { - pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount { - account_type: AccountType::ServiceAccount, - entry_managed_by: Some(UUID_IDM_ADMINS), - name: "anonymous", - uuid: UUID_ANONYMOUS, - description: "Anonymous access account.", - displayname: "Anonymous", - }; -} - -pub fn builtin_accounts() -> Vec<&'static BuiltinAccount> { - vec![ - &BUILTIN_ACCOUNT_ADMIN, - &BUILTIN_ACCOUNT_IDM_ADMIN, - &BUILTIN_ACCOUNT_ANONYMOUS_DL6, - ] -} - // ============ TEST DATA ============ #[cfg(test)] -pub const UUID_TESTPERSON_1: Uuid = ::uuid::uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"); - -#[cfg(test)] -pub const UUID_TESTPERSON_2: Uuid = ::uuid::uuid!("538faac7-4d29-473b-a59d-23023ac19955"); +use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew}; #[cfg(test)] lazy_static! { @@ -363,7 +206,10 @@ lazy_static! { (Attribute::Class, EntryClass::Person.to_value()), (Attribute::Name, Value::new_iname("testperson1")), (Attribute::DisplayName, Value::new_utf8s("Test Person 1")), - (Attribute::Uuid, Value::Uuid(UUID_TESTPERSON_1)) + ( + Attribute::Uuid, + Value::Uuid(super::uuids::UUID_TESTPERSON_1) + ) ); pub static ref E_TESTPERSON_2: EntryInitNew = entry_init!( (Attribute::Class, EntryClass::Object.to_value()), @@ -371,28 +217,9 @@ lazy_static! { (Attribute::Class, EntryClass::Person.to_value()), (Attribute::Name, Value::new_iname("testperson2")), (Attribute::DisplayName, Value::new_utf8s("Test Person 2")), - (Attribute::Uuid, Value::Uuid(UUID_TESTPERSON_2)) + ( + Attribute::Uuid, + Value::Uuid(super::uuids::UUID_TESTPERSON_2) + ) ); } - -// ⚠️ DOMAIN LEVEL 1 ENTRIES ⚠️ -// Future entries need to be added via migrations. -// -// DO NOT MODIFY THIS DEFINITION - -/// Build a list of internal admin entries -pub fn idm_builtin_admin_entries() -> Result, OperationError> { - let mut res: Vec = vec![ - BUILTIN_ACCOUNT_ADMIN.clone().into(), - BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(), - ]; - for group in idm_builtin_admin_groups() { - let g: EntryInitNew = group.clone().try_into()?; - res.push(g); - } - - // We need to push anonymous *after* groups due to entry-managed-by - res.push(BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into()); - - Ok(res) -} diff --git a/server/lib/src/constants/mod.rs b/server/lib/src/constants/mod.rs index f9ebb387b..35be1d8b4 100644 --- a/server/lib/src/constants/mod.rs +++ b/server/lib/src/constants/mod.rs @@ -1,20 +1,10 @@ // Re-export as needed -pub mod acp; pub mod entries; -pub mod groups; -mod key_providers; -pub mod schema; -pub mod system_config; pub mod uuids; pub mod values; -pub use self::acp::*; pub use self::entries::*; -pub use self::groups::*; -pub use self::key_providers::*; -pub use self::schema::*; -pub use self::system_config::*; pub use self::uuids::*; pub use self::values::*; diff --git a/server/lib/src/constants/uuids.rs b/server/lib/src/constants/uuids.rs index 1389f465c..a5da5dcb3 100644 --- a/server/lib/src/constants/uuids.rs +++ b/server/lib/src/constants/uuids.rs @@ -6,6 +6,7 @@ use uuid::{uuid, Uuid}; pub const STR_UUID_ADMIN: &str = "00000000-0000-0000-0000-000000000000"; pub const UUID_ADMIN: Uuid = uuid!("00000000-0000-0000-0000-000000000000"); pub const UUID_IDM_ADMINS: Uuid = uuid!("00000000-0000-0000-0000-000000000001"); +pub const NAME_IDM_ADMINS: &str = "idm_admins"; pub const UUID_IDM_PEOPLE_PII_READ: Uuid = uuid!("00000000-0000-0000-0000-000000000002"); pub const UUID_IDM_PEOPLE_WRITE_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000003"); pub const UUID_IDM_GROUP_WRITE_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000004"); @@ -26,6 +27,8 @@ pub const UUID_IDM_ADMIN: Uuid = uuid!("00000000-0000-0000-0000-000000000018"); pub const STR_UUID_SYSTEM_ADMINS: &str = "00000000-0000-0000-0000-000000000019"; pub const UUID_SYSTEM_ADMINS: Uuid = uuid!("00000000-0000-0000-0000-000000000019"); +pub const NAME_SYSTEM_ADMINS: &str = "system_admins"; + pub const UUID_DOMAIN_ADMINS: Uuid = uuid!("00000000-0000-0000-0000-000000000020"); pub const UUID_IDM_ACCOUNT_UNIX_EXTEND_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000021"); pub const UUID_IDM_GROUP_UNIX_EXTEND_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000022"); @@ -50,6 +53,7 @@ pub const UUID_IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV: Uuid = pub const UUID_IDM_ALL_PERSONS: Uuid = uuid!("00000000-0000-0000-0000-000000000035"); pub const STR_UUID_IDM_ALL_ACCOUNTS: &str = "00000000-0000-0000-0000-000000000036"; pub const UUID_IDM_ALL_ACCOUNTS: Uuid = uuid!("00000000-0000-0000-0000-000000000036"); +pub const NAME_IDM_ALL_ACCOUNTS: &str = "idm_all_accounts"; pub const UUID_IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV: Uuid = uuid!("00000000-0000-0000-0000-000000000037"); @@ -452,3 +456,9 @@ pub const UUID_DOES_NOT_EXIST: Uuid = uuid!("00000000-0000-0000-0000-fffffffffff pub const UUID_ANONYMOUS: Uuid = uuid!("00000000-0000-0000-0000-ffffffffffff"); pub const DYNAMIC_RANGE_MINIMUM_UUID: Uuid = uuid!("00000000-0000-0000-0001-000000000000"); + +// ======= test data ====== +#[cfg(test)] +pub const UUID_TESTPERSON_1: Uuid = uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"); +#[cfg(test)] +pub const UUID_TESTPERSON_2: Uuid = uuid!("538faac7-4d29-473b-a59d-23023ac19955"); diff --git a/server/lib/src/event.rs b/server/lib/src/event.rs index 6b98f97f6..e9019693e 100644 --- a/server/lib/src/event.rs +++ b/server/lib/src/event.rs @@ -636,23 +636,6 @@ impl ModifyEvent { } } - /// ⚠️ - Bypass the schema state machine and force the filter to be considered valid. - /// This is a TEST ONLY method and will never be exposed in production. - #[cfg(test)] - pub fn new_impersonate_entry_ser( - e: BuiltinAccount, - filter: Filter, - modlist: ModifyList, - ) -> Self { - let ei: EntryInitNew = e.into(); - ModifyEvent { - ident: Identity::from_impersonate_entry_readwrite(Arc::new(ei.into_sealed_committed())), - filter: filter.clone().into_valid(), - filter_orig: filter.into_valid(), - modlist: modlist.into_valid(), - } - } - /// ⚠️ - Bypass the schema state machine and force the filter to be considered valid. /// This is a TEST ONLY method and will never be exposed in production. #[cfg(test)] diff --git a/server/lib/src/idm/account.rs b/server/lib/src/idm/account.rs index abe011de4..17b481f78 100644 --- a/server/lib/src/idm/account.rs +++ b/server/lib/src/idm/account.rs @@ -1041,18 +1041,10 @@ impl IdmServerProxyReadTransaction<'_> { #[cfg(test)] mod tests { - use crate::idm::account::Account; use crate::idm::accountpolicy::ResolvedAccountPolicy; use crate::prelude::*; use kanidm_proto::internal::UiHint; - #[test] - fn test_idm_account_from_anonymous() { - let account: Account = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(); - debug!("{:?}", account); - // I think that's it? we may want to check anonymous mech ... - } - #[idm_test] async fn test_idm_account_ui_hints(idms: &IdmServer, _idms_delayed: &mut IdmServerDelayed) { let ct = duration_from_epoch_now(); diff --git a/server/lib/src/idm/authsession.rs b/server/lib/src/idm/authsession.rs index 0d544019e..02cdb96c8 100644 --- a/server/lib/src/idm/authsession.rs +++ b/server/lib/src/idm/authsession.rs @@ -1716,6 +1716,7 @@ mod tests { }; use crate::idm::delayed::DelayedAction; use crate::idm::AuthState; + use crate::migration_data::{BUILTIN_ACCOUNT_ANONYMOUS, BUILTIN_ACCOUNT_TEST_PERSON}; use crate::prelude::*; use crate::server::keys::KeyObjectInternal; use crate::utils::readable_password_from_random; @@ -1742,7 +1743,7 @@ mod tests { let webauthn = create_webauthn(); - let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(); + let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS.clone().into(); let asd = AuthSessionData { account: anon_account, @@ -1819,7 +1820,7 @@ mod tests { fn start_session_simple_password_mech(privileged: bool) -> UserAuthToken { let webauthn = create_webauthn(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); // manually load in a cred let p = CryptoPolicy::minimum(); let cred = Credential::new_password_only(&p, "test_password").unwrap(); @@ -1920,7 +1921,7 @@ mod tests { sketching::test_init(); let webauthn = create_webauthn(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); // manually load in a cred let p = CryptoPolicy::minimum(); let cred = Credential::new_password_only(&p, "list@no3IBTyqHu$bad").unwrap(); @@ -2087,7 +2088,7 @@ mod tests { sketching::test_init(); let webauthn = create_webauthn(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); @@ -2264,7 +2265,7 @@ mod tests { sketching::test_init(); let webauthn = create_webauthn(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); @@ -2440,7 +2441,7 @@ mod tests { let (audit_tx, mut audit_rx) = unbounded(); let ts = duration_from_epoch_now(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); let (webauthn, mut wa, wan_cred) = setup_webauthn_passkey(account.name.as_str()); @@ -2594,7 +2595,7 @@ mod tests { let (audit_tx, mut audit_rx) = unbounded(); let ts = duration_from_epoch_now(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); let (webauthn, mut wa, wan_cred) = setup_webauthn_securitykey(account.name.as_str()); let pw_good = "test_password"; @@ -2787,7 +2788,7 @@ mod tests { let (audit_tx, mut audit_rx) = unbounded(); let ts = duration_from_epoch_now(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); let (webauthn, mut wa, wan_cred) = setup_webauthn_securitykey(account.name.as_str()); @@ -3053,7 +3054,7 @@ mod tests { sketching::test_init(); let webauthn = create_webauthn(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); @@ -3262,7 +3263,7 @@ mod tests { sketching::test_init(); let webauthn = create_webauthn(); // create the ent - let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); + let mut account: Account = BUILTIN_ACCOUNT_TEST_PERSON.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); diff --git a/server/lib/src/idm/ldap.rs b/server/lib/src/idm/ldap.rs index de521bd78..4b7a4e37e 100644 --- a/server/lib/src/idm/ldap.rs +++ b/server/lib/src/idm/ldap.rs @@ -1989,7 +1989,7 @@ mod tests { let me = ModifyEvent::new_internal_invalid( filter!(f_eq( Attribute::Name, - PartialValue::new_iname(BUILTIN_GROUP_PEOPLE_PII_READ.name) + PartialValue::new_iname("idm_people_pii_read") )), ModifyList::new_list(vec![Modify::Present( Attribute::Member, diff --git a/server/lib/src/lib.rs b/server/lib/src/lib.rs index 562042536..870b19b0b 100644 --- a/server/lib/src/lib.rs +++ b/server/lib/src/lib.rs @@ -50,6 +50,12 @@ pub mod credential; pub mod entry; pub mod event; pub mod filter; + +// If this module is ever made public outside of this crate, firstyear will be extremely sad. +// This is *purely migration data*. Don't even think about using it in test cases for anything +// else. +pub(crate) mod migration_data; + pub mod modify; pub mod time; pub(crate) mod utils; diff --git a/server/lib/src/constants/acp.rs b/server/lib/src/migration_data/dl10/access.rs similarity index 100% rename from server/lib/src/constants/acp.rs rename to server/lib/src/migration_data/dl10/access.rs diff --git a/server/lib/src/migration_data/dl10/accounts.rs b/server/lib/src/migration_data/dl10/accounts.rs new file mode 100644 index 000000000..f7b6a065a --- /dev/null +++ b/server/lib/src/migration_data/dl10/accounts.rs @@ -0,0 +1,35 @@ +//! Constant Entries for the IDM +use crate::constants::uuids::*; +use crate::migration_data::types::BuiltinAccount; +use kanidm_proto::v1::AccountType; + +lazy_static! { + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "idm_admin", + uuid: UUID_IDM_ADMIN, + description: "Builtin IDM Admin account.", + displayname: "IDM Administrator", + }; + + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "admin", + uuid: UUID_ADMIN, + description: "Builtin System Admin account.", + displayname: "System Administrator", + }; + + pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: Some(UUID_IDM_ADMINS), + name: "anonymous", + uuid: UUID_ANONYMOUS, + description: "Anonymous access account.", + displayname: "Anonymous", + }; +} diff --git a/server/lib/src/migration_data/dl10/groups.rs b/server/lib/src/migration_data/dl10/groups.rs new file mode 100644 index 000000000..568bf8987 --- /dev/null +++ b/server/lib/src/migration_data/dl10/groups.rs @@ -0,0 +1,408 @@ +use crate::entry::EntryInitNew; +use crate::prelude::*; +use crate::value::CredentialType; + +use kanidm_proto::internal::{Filter, OperationError, UiHint}; + +#[derive(Clone, Debug, Default)] +/// Built-in group definitions +pub struct BuiltinGroup { + pub name: &'static str, + pub description: &'static str, + pub uuid: uuid::Uuid, + pub members: Vec, + pub entry_managed_by: Option, + pub dyngroup: bool, + pub dyngroup_filter: Option, + pub extra_attributes: Vec<(Attribute, Value)>, +} + +impl TryFrom for EntryInitNew { + type Error = OperationError; + + fn try_from(val: BuiltinGroup) -> Result { + let mut entry = EntryInitNew::new(); + + if val.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { + error!("Builtin ACP has invalid UUID! {:?}", val); + return Err(OperationError::InvalidUuid); + } + + entry.add_ava(Attribute::Name, Value::new_iname(val.name)); + entry.add_ava(Attribute::Description, Value::new_utf8s(val.description)); + // classes for groups + entry.set_ava( + Attribute::Class, + vec![EntryClass::Group.into(), EntryClass::Object.into()], + ); + if val.dyngroup { + if !val.members.is_empty() { + return Err(OperationError::InvalidSchemaState(format!( + "Builtin dyngroup {} has members specified, this is not allowed", + val.name + ))); + } + entry.add_ava(Attribute::Class, EntryClass::DynGroup.to_value()); + match val.dyngroup_filter { + Some(filter) => entry.add_ava(Attribute::DynGroupFilter, Value::JsonFilt(filter)), + None => { + error!( + "No filter specified for dyngroup '{}' this is going to break things!", + val.name + ); + return Err(OperationError::FilterGeneration); + } + }; + } + + if let Some(entry_manager) = val.entry_managed_by { + entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager)); + } + + entry.add_ava(Attribute::Uuid, Value::Uuid(val.uuid)); + entry.set_ava( + Attribute::Member, + val.members + .into_iter() + .map(Value::Refer) + .collect::>(), + ); + // add any extra attributes + val.extra_attributes + .into_iter() + .for_each(|(attr, val)| entry.add_ava(attr, val)); + // all done! + Ok(entry) + } +} + +lazy_static! { + // There are our built in "roles". They encapsulate some higher level collections + // of roles. The intent is to allow a pretty generic and correct by default set + // of these use cases. + pub static ref BUILTIN_GROUP_SYSTEM_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: NAME_SYSTEM_ADMINS, + description: "Builtin System Administrators Group.", + uuid: UUID_SYSTEM_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_ADMIN], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_IDM_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: NAME_IDM_ADMINS, + description: "Builtin IDM Administrators Group.", + uuid: UUID_IDM_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMIN], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SERVICE_DESK: BuiltinGroup = BuiltinGroup { + name: "idm_service_desk", + description: "Builtin Service Desk Group.", + uuid: UUID_IDM_SERVICE_DESK, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![], + ..Default::default() + }; +} + +lazy_static! { + // These are the "finer" roles. They encapsulate different concepts in the system. + // The next section is the "system style" roles. These adjust the operation of + // kanidm and relate to it's internals and how it functions. + pub static ref BUILTIN_GROUP_RECYCLE_BIN_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_recycle_bin_admins", + description: "Builtin Recycle Bin Administrators Group.", + uuid: UUID_IDM_RECYCLE_BIN_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for granting local domain administration rights and trust administration rights + pub static ref BUILTIN_GROUP_DOMAIN_ADMINS: BuiltinGroup = BuiltinGroup { + name: "domain_admins", + description: "Builtin IDM Group for granting local domain administration rights and trust administration rights.", + uuid: UUID_DOMAIN_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SCHEMA_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_schema_admins", + description: "Builtin Schema Administration Group.", + uuid: UUID_IDM_SCHEMA_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_ACCESS_CONTROL_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_access_control_admins", + description: "Builtin Access Control Administration Group.", + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + uuid: UUID_IDM_ACCESS_CONTROL_ADMINS, + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + // These are the IDM roles. They concern application integration, user permissions + // and credential security management. + + /// Builtin IDM Group for managing persons and their account details + pub static ref BUILTIN_GROUP_PEOPLE_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_people_admins", + description: "Builtin People Administration Group.", + uuid: UUID_IDM_PEOPLE_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_PEOPLE_ON_BOARDING: BuiltinGroup = BuiltinGroup { + name: "idm_people_on_boarding", + description: "Builtin People On Boarding Group.", + uuid: UUID_IDM_PEOPLE_ON_BOARDING, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![], + ..Default::default() + }; + + /// Builtin IDM Group for granting elevated people (personal data) read permissions. + pub static ref BUILTIN_GROUP_PEOPLE_PII_READ: BuiltinGroup = BuiltinGroup { + name: "idm_people_pii_read", + description: "Builtin IDM Group for granting elevated people (personal data) read permissions.", + uuid: UUID_IDM_PEOPLE_PII_READ, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![], + ..Default::default() + }; + + /// Builtin IDM Group for granting people the ability to write to their own name attributes. + pub static ref BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7: BuiltinGroup = BuiltinGroup { + name: "idm_people_self_name_write", + description: "Builtin IDM Group denoting users that can write to their own name attributes.", + uuid: UUID_IDM_PEOPLE_SELF_NAME_WRITE, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![ + UUID_IDM_ALL_PERSONS + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_service_account_admins", + description: "Builtin Service Account Administration Group.", + uuid: UUID_IDM_SERVICE_ACCOUNT_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain. + pub static ref BUILTIN_GROUP_OAUTH2_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_oauth2_admins", + description: "Builtin Oauth2 Integration Administration Group.", + uuid: UUID_IDM_OAUTH2_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_RADIUS_SERVICE_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_radius_service_admins", + description: "Builtin Radius Administration Group.", + uuid: UUID_IDM_RADIUS_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for RADIUS server access delegation. + pub static ref BUILTIN_IDM_RADIUS_SERVERS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_radius_servers", + description: "Builtin IDM Group for RADIUS server access delegation.", + uuid: UUID_IDM_RADIUS_SERVERS, + entry_managed_by: Some(UUID_IDM_RADIUS_ADMINS), + members: vec![ + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_mail_service_admins", + description: "Builtin Mail Server Administration Group.", + uuid: UUID_IDM_MAIL_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for MAIL server Access delegation. + pub static ref BUILTIN_IDM_MAIL_SERVERS_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_mail_servers", + description: "Builtin IDM Group for MAIL server access delegation.", + uuid: UUID_IDM_MAIL_SERVERS, + entry_managed_by: Some(UUID_IDM_MAIL_ADMINS), + members: vec![ + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_account_policy_admins", + description: "Builtin Account Policy Administration Group.", + uuid: UUID_IDM_ACCOUNT_POLICY_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for managing posix/unix attributes on groups and users. + pub static ref BUILTIN_GROUP_UNIX_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_unix_admins", + description: "Builtin Unix Administration Group.", + uuid: UUID_IDM_UNIX_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for managing client authentication certificates. + pub static ref BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7: BuiltinGroup = BuiltinGroup { + name: "idm_client_certificate_admins", + description: "Builtin Client Certificate Administration Group.", + uuid: UUID_IDM_CLIENT_CERTIFICATE_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for granting elevated group write and lifecycle permissions. + pub static ref IDM_GROUP_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_group_admins", + description: "Builtin IDM Group for granting elevated group write and lifecycle permissions.", + uuid: UUID_IDM_GROUP_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Self-write of mail + pub static ref IDM_PEOPLE_SELF_MAIL_WRITE_DL7: BuiltinGroup = BuiltinGroup { + name: "idm_people_self_mail_write", + description: "Builtin IDM Group for people accounts to update their own mail.", + uuid: UUID_IDM_PEOPLE_SELF_MAIL_WRITE, + members: Vec::with_capacity(0), + ..Default::default() + }; +} + +// at some point vs code just gives up on syntax highlighting inside lazy_static... +lazy_static! { + pub static ref IDM_ALL_PERSONS: BuiltinGroup = BuiltinGroup { + name: "idm_all_persons", + description: "Builtin IDM dynamic group containing all persons.", + uuid: UUID_IDM_ALL_PERSONS, + members: Vec::with_capacity(0), + dyngroup: true, + dyngroup_filter: Some( + Filter::And(vec![ + Filter::Eq(Attribute::Class.to_string(), EntryClass::Person.to_string()), + Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()), + ]) + ), + extra_attributes: vec![ + // Enable account policy by default + (Attribute::Class, EntryClass::AccountPolicy.to_value()), + // Enforce this is a system protected object + (Attribute::Class, EntryClass::System.to_value()), + // MFA By Default + (Attribute::CredentialTypeMinimum, CredentialType::Mfa.into()), + ], + ..Default::default() + }; + + pub static ref IDM_ALL_ACCOUNTS: BuiltinGroup = BuiltinGroup { + name: NAME_IDM_ALL_ACCOUNTS, + description: "Builtin IDM dynamic group containing all entries that can authenticate.", + uuid: UUID_IDM_ALL_ACCOUNTS, + members: Vec::with_capacity(0), + dyngroup: true, + dyngroup_filter: Some( + Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()), + ), + extra_attributes: vec![ + // Enable account policy by default + (Attribute::Class, EntryClass::AccountPolicy.to_value()), + // Enforce this is a system protected object + (Attribute::Class, EntryClass::System.to_value()), + ], + ..Default::default() + }; + + + pub static ref IDM_UI_ENABLE_EXPERIMENTAL_FEATURES: BuiltinGroup = BuiltinGroup { + name: "idm_ui_enable_experimental_features", + description: "Members of this group will have access to experimental web UI features.", + uuid: UUID_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES, + entry_managed_by: Some(UUID_IDM_ADMINS), + extra_attributes: vec![ + (Attribute::GrantUiHint, Value::UiHint(UiHint::ExperimentalFeatures)) + ], + ..Default::default() + }; + + /// Members of this group will have access to read the mail attribute of all persons and service accounts. + pub static ref IDM_ACCOUNT_MAIL_READ: BuiltinGroup = BuiltinGroup { + name: "idm_account_mail_read", + description: "Members of this group will have access to read the mail attribute of all persons and service accounts.", + entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS), + uuid: UUID_IDM_ACCOUNT_MAIL_READ, + ..Default::default() + }; + + /// This must be the last group to init to include the UUID of the other high priv groups. + pub static ref IDM_HIGH_PRIVILEGE_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_high_privilege", + uuid: UUID_IDM_HIGH_PRIVILEGE, + entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS), + description: "Builtin IDM provided groups with high levels of access that should be audited and limited in modification.", + members: vec![ + UUID_SYSTEM_ADMINS, + UUID_IDM_ADMINS, + UUID_DOMAIN_ADMINS, + UUID_IDM_SERVICE_DESK, + UUID_IDM_RECYCLE_BIN_ADMINS, + UUID_IDM_SCHEMA_ADMINS, + UUID_IDM_ACCESS_CONTROL_ADMINS, + UUID_IDM_OAUTH2_ADMINS, + UUID_IDM_RADIUS_ADMINS, + UUID_IDM_ACCOUNT_POLICY_ADMINS, + UUID_IDM_RADIUS_SERVERS, + UUID_IDM_GROUP_ADMINS, + UUID_IDM_UNIX_ADMINS, + UUID_IDM_PEOPLE_PII_READ, + UUID_IDM_PEOPLE_ADMINS, + UUID_IDM_PEOPLE_ON_BOARDING, + UUID_IDM_SERVICE_ACCOUNT_ADMINS, + UUID_IDM_CLIENT_CERTIFICATE_ADMINS, + UUID_IDM_APPLICATION_ADMINS, + UUID_IDM_MAIL_ADMINS, + UUID_IDM_HIGH_PRIVILEGE, + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_APPLICATION_ADMINS_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_application_admins", + uuid: UUID_IDM_APPLICATION_ADMINS, + description: "Builtin Application Administration Group.", + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; +} diff --git a/server/lib/src/constants/key_providers.rs b/server/lib/src/migration_data/dl10/key_providers.rs similarity index 100% rename from server/lib/src/constants/key_providers.rs rename to server/lib/src/migration_data/dl10/key_providers.rs diff --git a/server/lib/src/migration_data/dl10/mod.rs b/server/lib/src/migration_data/dl10/mod.rs new file mode 100644 index 000000000..b4b961824 --- /dev/null +++ b/server/lib/src/migration_data/dl10/mod.rs @@ -0,0 +1,268 @@ +mod access; +pub(super) mod accounts; +mod groups; +mod key_providers; +mod schema; +mod system_config; + +use self::access::*; +use self::accounts::*; +use self::groups::*; +use self::key_providers::*; +use self::schema::*; +use self::system_config::*; + +use crate::prelude::EntryInitNew; +use kanidm_proto::internal::OperationError; + +pub fn phase_1_schema_attrs() -> Vec { + vec![ + SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(), + SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(), + SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(), + SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(), + SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(), + SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(), + SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(), + SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(), + SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(), + SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(), + SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(), + SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(), + SCHEMA_ATTR_DOMAIN_NAME.clone().into(), + SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(), + SCHEMA_ATTR_DOMAIN_SSID.clone().into(), + SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(), + SCHEMA_ATTR_DOMAIN_UUID.clone().into(), + SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(), + SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(), + SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(), + SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(), + SCHEMA_ATTR_GIDNUMBER.clone().into(), + SCHEMA_ATTR_GRANT_UI_HINT.clone().into(), + SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(), + SCHEMA_ATTR_LOGINSHELL.clone().into(), + SCHEMA_ATTR_NAME_HISTORY.clone().into(), + SCHEMA_ATTR_NSUNIQUEID.clone().into(), + SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE + .clone() + .into(), + SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(), + SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(), + SCHEMA_ATTR_OAUTH2_SESSION.clone().into(), + SCHEMA_ATTR_PASSKEYS.clone().into(), + SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(), + SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(), + SCHEMA_ATTR_RADIUS_SECRET.clone().into(), + SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(), + SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(), + SCHEMA_ATTR_SYNC_COOKIE.clone().into(), + SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_UNIX_PASSWORD.clone().into(), + SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_DENIED_NAME.clone().into(), + SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(), + SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(), + // DL4 + SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(), + SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4 + .clone() + .into(), + // DL5 + // DL6 + SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(), + SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(), + SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(), + SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(), + // DL7 + SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(), + SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(), + SCHEMA_ATTR_REFERS_DL7.clone().into(), + SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(), + SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(), + SCHEMA_ATTR_MAIL_DL7.clone().into(), + SCHEMA_ATTR_LEGALNAME_DL7.clone().into(), + SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(), + // DL8 + SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(), + SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(), + SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(), + // DL9 + SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(), + SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(), + // DL10 + SCHEMA_ATTR_DENIED_NAME_DL10.clone().into(), + SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES.clone().into(), + ] +} + +pub fn phase_2_schema_classes() -> Vec { + vec![ + SCHEMA_CLASS_DYNGROUP.clone().into(), + SCHEMA_CLASS_ORGPERSON.clone().into(), + SCHEMA_CLASS_POSIXACCOUNT.clone().into(), + SCHEMA_CLASS_POSIXGROUP.clone().into(), + SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(), + // DL4 + SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(), + // DL5 + SCHEMA_CLASS_ACCOUNT_DL5.clone().into(), + SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(), + // DL6 + SCHEMA_CLASS_GROUP_DL6.clone().into(), + SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(), + SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(), + // DL7 + SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(), + SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(), + SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(), + // DL8 + SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(), + SCHEMA_CLASS_APPLICATION_DL8.clone().into(), + SCHEMA_CLASS_PERSON_DL8.clone().into(), + // DL9 + SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(), + // DL10 + SCHEMA_CLASS_DOMAIN_INFO_DL10.clone().into(), + ] +} + +pub fn phase_3_key_provider() -> Vec { + vec![E_KEY_PROVIDER_INTERNAL_DL6.clone()] +} + +pub fn phase_4_system_entries() -> Vec { + vec![ + E_SYSTEM_INFO_V1.clone(), + E_DOMAIN_INFO_DL6.clone(), + E_SYSTEM_CONFIG_V1.clone(), + ] +} + +pub fn phase_5_builtin_admin_entries() -> Result, OperationError> { + Ok(vec![ + BUILTIN_ACCOUNT_ADMIN.clone().into(), + BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(), + BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?, + BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?, + // We need to push anonymous *after* groups due to entry-managed-by + BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(), + ]) +} + +pub fn phase_6_builtin_non_admin_entries() -> Result, OperationError> { + Ok(vec![ + BUILTIN_GROUP_DOMAIN_ADMINS.clone().try_into()?, + BUILTIN_GROUP_SCHEMA_ADMINS.clone().try_into()?, + BUILTIN_GROUP_ACCESS_CONTROL_ADMINS.clone().try_into()?, + BUILTIN_GROUP_UNIX_ADMINS.clone().try_into()?, + BUILTIN_GROUP_RECYCLE_BIN_ADMINS.clone().try_into()?, + BUILTIN_GROUP_SERVICE_DESK.clone().try_into()?, + BUILTIN_GROUP_OAUTH2_ADMINS.clone().try_into()?, + BUILTIN_GROUP_RADIUS_SERVICE_ADMINS.clone().try_into()?, + BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_ADMINS.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_PII_READ.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_ON_BOARDING.clone().try_into()?, + BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS.clone().try_into()?, + BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8.clone().try_into()?, + IDM_GROUP_ADMINS_V1.clone().try_into()?, + IDM_ALL_PERSONS.clone().try_into()?, + IDM_ALL_ACCOUNTS.clone().try_into()?, + BUILTIN_IDM_RADIUS_SERVERS_V1.clone().try_into()?, + BUILTIN_IDM_MAIL_SERVERS_DL8.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7 + .clone() + .try_into()?, + IDM_PEOPLE_SELF_MAIL_WRITE_DL7.clone().try_into()?, + BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7 + .clone() + .try_into()?, + BUILTIN_GROUP_APPLICATION_ADMINS_DL8.clone().try_into()?, + // Write deps on read.clone().try_into()?, so write must be added first. + // All members must exist before we write HP + IDM_HIGH_PRIVILEGE_DL8.clone().try_into()?, + // other things + IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone().try_into()?, + IDM_ACCOUNT_MAIL_READ.clone().try_into()?, + ]) +} + +pub fn phase_7_builtin_access_control_profiles() -> Vec { + vec![ + // Built in access controls. + IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(), + IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(), + IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(), + IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(), + IDM_ACP_ACP_MANAGE_V1.clone().into(), + IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(), + IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(), + IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(), + IDM_ACP_RADIUS_SERVERS_V1.clone().into(), + IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(), + IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(), + IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(), + IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1 + .clone() + .into(), + IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(), + IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(), + IDM_ACP_GROUP_READ_V1.clone().into(), + IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(), + IDM_ACP_PEOPLE_PII_READ_V1.clone().into(), + IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_READ_V1.clone().into(), + IDM_ACP_PEOPLE_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_DELETE_V1.clone().into(), + IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), + IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 + .clone() + .into(), + IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 + .clone() + .into(), + IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(), + // DL4 + // DL5 + // DL6 + IDM_ACP_PEOPLE_CREATE_DL6.clone().into(), + IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(), + // DL7 + IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(), + IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(), + // DL8 + IDM_ACP_SELF_READ_DL8.clone().into(), + IDM_ACP_SELF_WRITE_DL8.clone().into(), + IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(), + IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(), + IDM_ACP_MAIL_SERVERS_DL8.clone().into(), + IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(), + // DL9 + IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(), + IDM_ACP_GROUP_MANAGE_DL9.clone().into(), + IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(), + ] +} diff --git a/server/lib/src/constants/schema.rs b/server/lib/src/migration_data/dl10/schema.rs similarity index 99% rename from server/lib/src/constants/schema.rs rename to server/lib/src/migration_data/dl10/schema.rs index 93abb84eb..0cfc290cb 100644 --- a/server/lib/src/constants/schema.rs +++ b/server/lib/src/migration_data/dl10/schema.rs @@ -1,7 +1,4 @@ -//! Core Constants -//! -//! Schema uuids start at `00000000-0000-0000-0000-ffff00000000` -//! +//! Schema Entries use crate::constants::entries::{Attribute, EntryClass}; use crate::constants::uuids::*; use crate::schema::{SchemaAttribute, SchemaClass}; diff --git a/server/lib/src/constants/system_config.rs b/server/lib/src/migration_data/dl10/system_config.rs similarity index 97% rename from server/lib/src/constants/system_config.rs rename to server/lib/src/migration_data/dl10/system_config.rs index 253d772e0..107bd8bbe 100644 --- a/server/lib/src/constants/system_config.rs +++ b/server/lib/src/migration_data/dl10/system_config.rs @@ -8,6 +8,31 @@ use crate::value::Value; // This is separated because the password badlist section may become very long lazy_static! { + pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::SystemInfo.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_SYSTEM_INFO)), + ( + Attribute::Description, + Value::new_utf8s("System (local) info and metadata object.") + ), + (Attribute::Version, Value::Uint32(20)) + ); + pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::DomainInfo.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Class, EntryClass::KeyObject.to_value()), + (Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()), + (Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()), + (Attribute::Name, Value::new_iname("domain_local")), + (Attribute::Uuid, Value::Uuid(UUID_DOMAIN_INFO)), + ( + Attribute::Description, + Value::new_utf8s("This local domain's info and metadata object.") + ) + ); pub static ref E_SYSTEM_CONFIG_V1: EntryInitNew = entry_init!( (Attribute::Class, EntryClass::Object.to_value()), (Attribute::Class, EntryClass::SystemConfig.to_value()), diff --git a/server/lib/src/migration_data/dl8/access.rs b/server/lib/src/migration_data/dl8/access.rs new file mode 100644 index 000000000..7c0487745 --- /dev/null +++ b/server/lib/src/migration_data/dl8/access.rs @@ -0,0 +1,2637 @@ +#![allow(clippy::expect_used)] +//! Constant Entries for the IDM + +use crate::constants::uuids::*; +use crate::entry::EntryInitNew; +use crate::prelude::*; +use crate::value::Value; +use kanidm_proto::internal::Filter as ProtoFilter; + +lazy_static! { + /// either recycled or tombstone + pub static ref FILTER_RECYCLED_OR_TOMBSTONE: ProtoFilter = ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Recycled), + match_class_filter!(EntryClass::Tombstone), + ]); + + /// not either recycled or tombstone + pub static ref FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED: ProtoFilter = + ProtoFilter::AndNot(Box::new(FILTER_RECYCLED_OR_TOMBSTONE.clone())); + + /// members of 000000001000 / idm_high_privilege + pub static ref FILTER_HP: ProtoFilter = ProtoFilter::Eq( + Attribute::MemberOf.to_string(), + UUID_IDM_HIGH_PRIVILEGE.to_string(), + ); + + /// OR ( HP, Recycled, Tombstone) + pub static ref FILTER_HP_OR_RECYCLED_OR_TOMBSTONE: ProtoFilter = ProtoFilter::Or(vec![ + FILTER_HP.clone(), + match_class_filter!(EntryClass::Recycled), + match_class_filter!(EntryClass::Tombstone), + ]); + + pub static ref FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE: ProtoFilter = + ProtoFilter::AndNot(Box::new(FILTER_HP_OR_RECYCLED_OR_TOMBSTONE.clone())); + + pub static ref DEFAULT_TARGET_SCOPE: ProtoFilter = ProtoFilter::And(Vec::with_capacity(0)); + +} + +#[derive(Clone, Debug, Default)] +/// Who will receive the privileges of this ACP. +pub enum BuiltinAcpReceiver { + #[default] + None, + /// This functions as an "OR" condition, that membership of *at least one* of these UUIDs + /// is sufficient for you to receive the access control. + Group(Vec), + EntryManager, +} + +#[derive(Clone, Debug, Default)] +/// Objects that are affected by the rules of this ACP. +pub enum BuiltinAcpTarget { + #[default] + None, + // Self, + Filter(ProtoFilter), + // MemberOf ( Uuid ), +} + +#[derive(Clone, Debug, Default)] +/// Built-in Access Control Profile definitions +pub struct BuiltinAcp { + classes: Vec, + pub name: &'static str, + uuid: Uuid, + description: &'static str, + receiver: BuiltinAcpReceiver, + target: BuiltinAcpTarget, + search_attrs: Vec, + modify_present_attrs: Vec, + modify_removed_attrs: Vec, + modify_classes: Vec, + create_classes: Vec, + create_attrs: Vec, +} + +impl From for EntryInitNew { + #[allow(clippy::panic)] + fn from(value: BuiltinAcp) -> Self { + let mut entry = EntryInitNew::default(); + + #[allow(clippy::panic)] + if value.name.is_empty() { + panic!("Builtin ACP has no name! {:?}", value); + } + #[allow(clippy::panic)] + if value.classes.is_empty() { + panic!("Builtin ACP has no classes! {:?}", value); + } + + value.classes.iter().for_each(|class| { + entry.add_ava(Attribute::Class, class.to_value()); + }); + + entry.set_ava(Attribute::Name, [Value::new_iname(value.name)]); + + if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { + panic!("Builtin ACP has invalid UUID! {:?}", value); + } + + entry.set_ava(Attribute::Uuid, [Value::Uuid(value.uuid)]); + entry.set_ava( + Attribute::Description, + [Value::new_utf8s(value.description)], + ); + + match &value.receiver { + #[allow(clippy::panic)] + BuiltinAcpReceiver::None => { + panic!("Builtin ACP has no receiver! {:?}", &value); + } + BuiltinAcpReceiver::Group(list) => { + entry.add_ava( + Attribute::Class, + EntryClass::AccessControlReceiverGroup.to_value(), + ); + for group in list { + entry.set_ava(Attribute::AcpReceiverGroup, [Value::Refer(*group)]); + } + } + BuiltinAcpReceiver::EntryManager => { + entry.add_ava( + Attribute::Class, + EntryClass::AccessControlReceiverEntryManager.to_value(), + ); + } + }; + + match &value.target { + #[allow(clippy::panic)] + BuiltinAcpTarget::None => { + panic!("Builtin ACP has no target! {:?}", &value); + } + BuiltinAcpTarget::Filter(proto_filter) => { + entry.add_ava( + Attribute::Class, + EntryClass::AccessControlTargetScope.to_value(), + ); + entry.set_ava( + Attribute::AcpTargetScope, + [Value::JsonFilt(proto_filter.clone())], + ); + } + } + + entry.set_ava( + Attribute::AcpSearchAttr, + value + .search_attrs + .into_iter() + .map(Value::from) + .collect::>(), + ); + value.modify_present_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpModifyPresentAttr, Value::from(attr)); + }); + value.modify_removed_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpModifyRemovedAttr, Value::from(attr)); + }); + value.modify_classes.into_iter().for_each(|class| { + entry.add_ava(Attribute::AcpModifyClass, Value::from(class)); + }); + value.create_classes.into_iter().for_each(|class| { + entry.add_ava(Attribute::AcpCreateClass, Value::from(class)); + }); + value.create_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpCreateAttr, Value::from(attr)); + }); + entry + } +} + +lazy_static! { + pub static ref IDM_ACP_RECYCLE_BIN_SEARCH_V1: BuiltinAcp = BuiltinAcp { + uuid: UUID_IDM_ACP_RECYCLE_BIN_SEARCH_V1, + name: "idm_acp_recycle_bin_search", + description: "Builtin IDM recycle bin search permission.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RECYCLE_BIN_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::Eq( + Attribute::Class.to_string(), + ATTR_RECYCLED.to_string() + )), + + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::LastModifiedCid, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_RECYCLE_BIN_REVIVE_V1: BuiltinAcp = BuiltinAcp { + uuid: UUID_IDM_ACP_RECYCLE_BIN_REVIVE_V1, + name: "idm_acp_recycle_bin_revive", + description: "Builtin IDM recycle bin revive permission.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RECYCLE_BIN_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::Eq( + Attribute::Class.to_string(), + ATTR_RECYCLED.to_string() + )), + modify_removed_attrs: vec![Attribute::Class], + modify_classes: vec![EntryClass::Recycled], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SCHEMA_WRITE_ATTRS_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_schema_write_attrs", + uuid: UUID_IDM_ACP_SCHEMA_WRITE_ATTRS_V1, + description: "Builtin IDM Control for management of schema attributes.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_SCHEMA_ADMINS] ), + // has a class, and isn't recycled/tombstoned + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + ProtoFilter::Eq(EntryClass::Class.to_string(),EntryClass::AttributeType.to_string()), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::AttributeName, + Attribute::Syntax, + Attribute::Uuid, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::Syntax, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::Syntax, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::AttributeName, + Attribute::Syntax, + Attribute::Uuid, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::AttributeType, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SCHEMA_WRITE_CLASSES_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_schema_write_classes", + uuid: UUID_IDM_ACP_SCHEMA_WRITE_CLASSES_V1, + description: "Builtin IDM Control for management of schema classes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SCHEMA_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + EntryClass::Class.to_string(), + EntryClass::ClassType.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::ClassName, + Attribute::Description, + Attribute::SystemMay, + Attribute::May, + Attribute::SystemMust, + Attribute::Must, + Attribute::Uuid, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::May, + Attribute::Must, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::May, + Attribute::Must, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::ClassName, + Attribute::Description, + Attribute::May, + Attribute::Must, + Attribute::Uuid, + ], + create_classes: vec![EntryClass::Object, EntryClass::ClassType,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACP_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_acp_manage", + uuid: UUID_IDM_ACP_ACP_MANAGE_V1, + description: "Builtin IDM Control for access profiles management.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCESS_CONTROL_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + EntryClass::Class.to_string(), + EntryClass::AccessControlProfile.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + modify_classes: vec![ + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + EntryClass::AccessControlModify, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + ], + create_classes: vec![ + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + EntryClass::AccessControlModify, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + ], + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_read", + uuid: UUID_IDM_ACP_GROUP_READ, + description: + "Builtin IDM Control for allowing all groups to be read by access control admins", + receiver: BuiltinAcpReceiver::Group(vec![ + UUID_IDM_ACCESS_CONTROL_ADMINS, + // UUID_IDM_SERVICE_DESK, + // UUID_IDM_PEOPLE_ADMINS, + ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::DynMember, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::Member, + Attribute::EntryManagedBy, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_entry_managed_by_modify", + uuid: UUID_IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY, + description: "Builtin IDM Control for allowing entry_managed_by to be set on group entries", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCESS_CONTROL_ADMINS]), + 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::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![Attribute::EntryManagedBy], + modify_present_attrs: vec![Attribute::EntryManagedBy], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6: 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), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + modify_classes: vec![EntryClass::AccountPolicy,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8: 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), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + modify_classes: vec![EntryClass::AccountPolicy,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL4: 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL5: 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::Name, + Attribute::Spn, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Name, + Attribute::DisplayName, + Attribute::OAuth2RsName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL7: 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::Name, + Attribute::Spn, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Name, + Attribute::DisplayName, + Attribute::OAuth2RsName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL9: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_oauth2_manage", + 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::Name, + Attribute::Spn, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Name, + Attribute::DisplayName, + Attribute::OAuth2RsName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_DOMAIN_ADMIN_DL6: 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, + // Grants read access to the key object. + // But this means we have to specify every type of key object? + // Future william problem ... + Attribute::KeyInternalData, + Attribute::LdapAllowUnixPwBind, + Attribute::Version, + ], + modify_removed_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + ], + modify_present_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_DOMAIN_ADMIN_DL8: 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::KeyInternalData, + Attribute::LdapAllowUnixPwBind, + Attribute::Version, + Attribute::Image, + ], + modify_removed_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + modify_present_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_DOMAIN_ADMIN_DL9: 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::DomainAllowEasterEggs, + Attribute::DomainDisplayName, + Attribute::DomainName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::DomainUuid, + Attribute::KeyInternalData, + Attribute::LdapAllowUnixPwBind, + Attribute::Version, + Attribute::Image, + ], + modify_removed_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::DomainAllowEasterEggs, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + modify_present_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::DomainAllowEasterEggs, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SYNC_ACCOUNT_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_sync_account_manage", + uuid: UUID_IDM_ACP_SYNC_ACCOUNT_MANAGE_V1, + description: "Builtin IDM Control for managing IDM synchronisation accounts / connections", + receiver: BuiltinAcpReceiver::Group(vec![UUID_DOMAIN_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + Attribute::Class.to_string(), + EntryClass::SyncAccount.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Description, + Attribute::JwsEs256PrivateKey, + Attribute::SyncTokenSession, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + Attribute::SyncCookie, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::JwsEs256PrivateKey, + Attribute::SyncTokenSession, + Attribute::SyncCredentialPortal, + Attribute::SyncCookie, + Attribute::SyncYieldAuthority, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::SyncTokenSession, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + ], + create_attrs: vec![Attribute::Class, Attribute::Name, Attribute::Description,], + create_classes: vec![EntryClass::Object, EntryClass::SyncAccount,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ENTRY_MANAGER_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_entry_manager", + uuid: UUID_IDM_ACP_GROUP_ENTRY_MANAGER_V1, + description: "Builtin IDM Control for allowing EntryManager to read and modify groups", + receiver: BuiltinAcpReceiver::EntryManager, + // Any group + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Uuid, + Attribute::Description, + Attribute::Member, + Attribute::DynMember, + Attribute::EntryManagedBy, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::Member, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::Member, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_RADIUS_SERVERS_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_radius_servers", + uuid: UUID_IDM_ACP_RADIUS_SERVERS_V1, + description: + "Builtin IDM Control for RADIUS servers to read credentials and other needed details.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RADIUS_SERVERS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Pres(EntryClass::Class.to_string()), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::RadiusSecret, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_RADIUS_SECRET_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_radius_secret_manage", + uuid: UUID_IDM_ACP_RADIUS_SECRET_MANAGE_V1, + description: "Builtin IDM Control allowing reads and writes to user radius secrets.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RADIUS_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![Attribute::RadiusSecret], + modify_present_attrs: vec![Attribute::RadiusSecret], + modify_removed_attrs: vec![Attribute::RadiusSecret], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_MAIL_SERVERS_DL8: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_mail_servers", + uuid: UUID_IDM_ACP_MAIL_SERVERS, + description: + "Builtin IDM Control for MAIL servers to read email addresses and other needed attributes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_MAIL_SERVERS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::Group), + ]), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::DisplayName, + Attribute::Mail, + Attribute::Member, + Attribute::DynMember, + Attribute::MemberOf, + Attribute::GidNumber, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + name: "idm_acp_people_self_write_mail", + uuid: UUID_IDM_ACP_PEOPLE_SELF_WRITE_MAIL, + description: "Builtin IDM Control for self write of mail for people accounts.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_SELF_MAIL_WRITE]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + match_class_filter!(EntryClass::Account).clone(), + ProtoFilter::SelfUuid, + ])), + modify_removed_attrs: vec![Attribute::Mail], + modify_present_attrs: vec![Attribute::Mail], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_READ_V1: BuiltinAcp = BuiltinAcp { + name: "idm_acp_self_read", + uuid: UUID_IDM_ACP_SELF_READ, + description: + "Builtin IDM Control for self read - required for whoami and many other functions", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ALL_ACCOUNTS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Class, + Attribute::MemberOf, + Attribute::Mail, + Attribute::RadiusSecret, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::Uuid, + Attribute::SyncParentUuid, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PrimaryCredential, + Attribute::UserAuthTokenSession, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_READ_DL8: BuiltinAcp = BuiltinAcp { + name: "idm_acp_self_read", + uuid: UUID_IDM_ACP_SELF_READ, + description: + "Builtin IDM Control for self read - required for whoami and many other functions", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ALL_ACCOUNTS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Class, + Attribute::MemberOf, + Attribute::Mail, + Attribute::RadiusSecret, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::Uuid, + Attribute::SyncParentUuid, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PrimaryCredential, + Attribute::UserAuthTokenSession, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::ApplicationPassword, + Attribute::SshPublicKey, + Attribute::UnixPassword, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_WRITE_V1: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_write", + uuid: UUID_IDM_ACP_SELF_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write - required for people to update their own identities and credentials in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::DisplayName, + Attribute::LegalName, + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::UserAuthTokenSession, + Attribute::ApplicationPassword, + ], + modify_present_attrs: vec![ + Attribute::DisplayName, + Attribute::LegalName, + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::ApplicationPassword, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_WRITE_DL7: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_write", + uuid: UUID_IDM_ACP_SELF_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write - required for people to update their own credentials in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::UserAuthTokenSession, + ], + modify_present_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_WRITE_DL8: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_write", + uuid: UUID_IDM_ACP_SELF_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write - required for people to update their own credentials in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::UserAuthTokenSession, + Attribute::ApplicationPassword, + ], + modify_present_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::ApplicationPassword, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_NAME_WRITE_V1: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_name_write", + uuid: UUID_IDM_ACP_SELF_NAME_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write of name - required for people to update their own identities in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::Name, + ], + modify_present_attrs: vec![ + Attribute::Name, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_NAME_WRITE_DL7: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_name_write", + uuid: UUID_IDM_ACP_SELF_NAME_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write of name - required for people to update their own identities in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_PEOPLE_SELF_NAME_WRITE] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::SelfUuid, + match_class_filter!(EntryClass::Person).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACCOUNT_SELF_WRITE_V1: BuiltinAcp = BuiltinAcp { + name: "idm_acp_account_self_write", + uuid: UUID_IDM_ACP_ACCOUNT_SELF_WRITE_V1, + description: "Builtin IDM Control for self write - required for accounts to update their own session state.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify + ], + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_ACCOUNTS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::UserAuthTokenSession + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_all_accounts_posix_read", + uuid: UUID_IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1, + description: + "Builtin IDM Control for reading minimal posix attrs - applies anonymous and all authenticated accounts.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_ACCOUNTS] ), + target: BuiltinAcpTarget::Filter( ProtoFilter::And( + vec![ + ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::Group), + ]), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ] + )), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::DisplayName, + Attribute::Class, + Attribute::MemberOf, + Attribute::Member, + Attribute::DynMember, + Attribute::Uuid, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::SshPublicKey, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACCOUNT_MAIL_READ_DL6: 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 and group mail attributes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_MAIL_READ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::Group), + ]), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![Attribute::Mail], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_system_config_account_policy_manage", + uuid: UUID_IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1, + description: "Builtin IDM Control for granting system configuration of account policy", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_POLICY_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + Attribute::Uuid.to_string(), + STR_UUID_SYSTEM_CONFIG.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Description, + Attribute::BadlistPassword, + Attribute::DeniedName, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + Attribute::Version, + ], + modify_removed_attrs: vec![ + Attribute::BadlistPassword, + Attribute::DeniedName, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + ], + modify_present_attrs: vec![ + Attribute::BadlistPassword, + Attribute::DeniedName, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_HP_GROUP_UNIX_MANAGE_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_group_unix_manage", + uuid: UUID_IDM_ACP_HP_GROUP_UNIX_MANAGE_V1, + description: "Builtin IDM Control for managing and extending high privilege groups with unix attributes", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_UNIX_ADMINS] ), + // HP group, not Recycled/Tombstone + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_HP.clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::DynMember, + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::Member, + Attribute::GidNumber, + ], + modify_removed_attrs: vec![ + Attribute::GidNumber, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::GidNumber, + ], + modify_classes: vec![ + EntryClass::PosixGroup, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_MANAGE_DL6: 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::Mail, + Attribute::Member, + Attribute::DynMember, + Attribute::EntryManagedBy, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Group, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_MANAGE_DL9: 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::Mail, + Attribute::Member, + Attribute::DynMember, + Attribute::EntryManagedBy, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Group, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_UNIX_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_unix_manage", + uuid: UUID_IDM_ACP_GROUP_UNIX_MANAGE_V1, + description: "Builtin IDM Control for managing unix groups", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_UNIX_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + search_attrs: vec![ + Attribute::DynMember, + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::Member, + Attribute::GidNumber, + ], + modify_removed_attrs: vec![Attribute::GidNumber,], + modify_present_attrs: vec![Attribute::Class, Attribute::GidNumber,], + modify_classes: vec![EntryClass::PosixGroup,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACCOUNT_UNIX_EXTEND_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_account_unix_extend", + uuid: UUID_IDM_ACP_ACCOUNT_UNIX_EXTEND_V1, + description: "Builtin IDM Control for managing and extending unix accounts", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_UNIX_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::SshPublicKey, + ], + modify_removed_attrs: vec![ + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::SshPublicKey, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::SshPublicKey, + ], + modify_classes: vec![EntryClass::PosixAccount,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_PII_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_people_pii_read", + uuid: UUID_IDM_ACP_PEOPLE_PII_READ_V1, + description: "Builtin IDM Control for reading personal and sensitive data.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS, UUID_IDM_PEOPLE_PII_READ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Mail, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_PII_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify + ], + name: "idm_acp_people_pii_manage", + uuid: UUID_IDM_ACP_PEOPLE_PII_MANAGE_V1, + description: "Builtin IDM Control for modifying peoples personal and sensitive data", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Mail, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Mail, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_CREATE_DL6: 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::Uuid, + Attribute::Name, + Attribute::DisplayName, + Attribute::Mail, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + ], + create_classes: vec![EntryClass::Object, EntryClass::Account, EntryClass::Person,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + name: "idm_acp_people_manage", + uuid: UUID_IDM_ACP_PEOPLE_MANAGE_V1, + description: "Builtin IDM Control for management of peoples non sensitive attributes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + modify_removed_attrs: vec![Attribute::AccountExpire, Attribute::AccountValidFrom,], + modify_present_attrs: vec![Attribute::AccountExpire, Attribute::AccountValidFrom,], + ..Default::default() + }; +} + +// Person Read +lazy_static! { + pub static ref IDM_ACP_PEOPLE_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_people_read", + uuid: UUID_IDM_ACP_PEOPLE_READ_V1, + description: "Builtin IDM Control for reading non-sensitive data.", + receiver: BuiltinAcpReceiver::Group(vec![ + UUID_IDM_PEOPLE_ADMINS, + UUID_IDM_PEOPLE_PII_READ, + UUID_IDM_ACCOUNT_MAIL_READ, + UUID_IDM_SERVICE_DESK + ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::DisplayName, + Attribute::MemberOf, + Attribute::Uuid, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + ], + ..Default::default() + }; +} + +// Person Delete +lazy_static! { + pub static ref IDM_ACP_PEOPLE_DELETE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlDelete, + ], + name: "idm_acp_people_delete", + uuid: UUID_IDM_ACP_PEOPLE_DELETE_V1, + description: "Builtin IDM Control for deleting persons.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS,]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + ..Default::default() + }; +} + +// Person Account Credential Reset +lazy_static! { + pub static ref IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_people_credential_reset", + uuid: UUID_IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1, + description: "Builtin IDM Control for resetting peoples credentials ", + receiver: BuiltinAcpReceiver::Group(vec![ + UUID_IDM_PEOPLE_ADMINS, + UUID_IDM_SERVICE_DESK, + UUID_IDM_PEOPLE_ON_BOARDING, + ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Spn, + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_removed_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_present_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +// HP Person Account Credential Reset +lazy_static! { + pub static ref IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_people_credential_reset", + uuid: UUID_IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1, + description: "Builtin IDM Control for resetting high privilege peoples credentials ", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS,]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + match_class_filter!(EntryClass::Account), + FILTER_HP.clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Spn, + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_removed_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_present_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +// Service Account Create/Manage +// needs to be able to assign to entry managed by +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_CREATE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + ], + name: "idm_acp_service_account_create", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_CREATE_V1, + description: "Builtin IDM Control for creating new service accounts.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::DisplayName, + Attribute::EntryManagedBy, + Attribute::Description, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::ServiceAccount, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify + ], + name: "idm_acp_service_account_manage", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1, + description: "Builtin IDM Control for modifying service account data", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::Mail, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PrimaryCredential, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + ], + modify_present_attrs: vec![Attribute::Name, Attribute::DisplayName, Attribute::Mail,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_DELETE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlDelete, + ], + name: "idm_acp_service_account_delete", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_DELETE_V1, + description: "Builtin IDM Control for deleting service accounts.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + ..Default::default() + }; +} + +// Service Account Credential Manage +// entry managed by? + +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_service_account_entry_manager", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1, + description: "Builtin IDM Control for allowing entry managers to modify service accounts", + receiver: BuiltinAcpReceiver::EntryManager, + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::ServiceAccount), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + Attribute::DisplayName, + Attribute::SshPublicKey, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + ], + modify_removed_attrs: vec![ + Attribute::DisplayName, + Attribute::SshPublicKey, + Attribute::PrimaryCredential, + Attribute::UnixPassword, + // For legacy upgrades we allow removing this. + Attribute::PassKeys, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + ], + modify_present_attrs: vec![ + Attribute::DisplayName, + Attribute::SshPublicKey, + Attribute::PrimaryCredential, + // Should this be a thing? I think no? + // Attribute::UnixPassword, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::ApiTokenSession, + ], + ..Default::default() + }; +} + +// Service Account Access Manager +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_service_account_entry_managed_by_modify", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY, + description: + "Builtin IDM Control for allowing entry_managed_by to be set on service account entries", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![Attribute::EntryManagedBy], + modify_present_attrs: vec![Attribute::EntryManagedBy], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_service_account_entry_managed_by", + uuid: UUID_IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY, + description: "Builtin IDM Control for allowing entry_managed_by to be set on high priv service account entries", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCESS_CONTROL_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_HP.clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![Attribute::EntryManagedBy], + modify_present_attrs: vec![Attribute::EntryManagedBy], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_client_certificate_manager", + uuid: UUID_IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER, + description: "Builtin IDM Control for allowing client certificate management.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_CLIENT_CERTIFICATE_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + EntryClass::Class.to_string(), + EntryClass::ClientCertificate.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Certificate, + Attribute::Refers, + ], + modify_removed_attrs: vec![Attribute::Certificate, Attribute::Refers,], + modify_present_attrs: vec![Attribute::Certificate, Attribute::Refers,], + create_attrs: vec![Attribute::Class, Attribute::Certificate, Attribute::Refers,], + create_classes: vec![EntryClass::Object, EntryClass::ClientCertificate,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_APPLICATION_MANAGE_DL8: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_application_manage", + uuid: UUID_IDM_ACP_APPLICATION_MANAGE, + description: "Builtin IDM Control for creating and deleting applications in the directory", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_APPLICATION_ADMINS] ), + // Any application + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Application), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::ServiceAccount, + EntryClass::Application, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_application_entry_manager", + uuid: UUID_IDM_ACP_APPLICATION_ENTRY_MANAGER, + description: "Builtin IDM Control for allowing EntryManager to read and modify applications", + receiver: BuiltinAcpReceiver::EntryManager, + // Applications that belong to the Entry Manager. + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Application), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::Description, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::LinkedGroup, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::LinkedGroup, + ], + ..Default::default() + }; +} diff --git a/server/lib/src/migration_data/dl8/accounts.rs b/server/lib/src/migration_data/dl8/accounts.rs new file mode 100644 index 000000000..f7b6a065a --- /dev/null +++ b/server/lib/src/migration_data/dl8/accounts.rs @@ -0,0 +1,35 @@ +//! Constant Entries for the IDM +use crate::constants::uuids::*; +use crate::migration_data::types::BuiltinAccount; +use kanidm_proto::v1::AccountType; + +lazy_static! { + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "idm_admin", + uuid: UUID_IDM_ADMIN, + description: "Builtin IDM Admin account.", + displayname: "IDM Administrator", + }; + + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "admin", + uuid: UUID_ADMIN, + description: "Builtin System Admin account.", + displayname: "System Administrator", + }; + + pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: Some(UUID_IDM_ADMINS), + name: "anonymous", + uuid: UUID_ANONYMOUS, + description: "Anonymous access account.", + displayname: "Anonymous", + }; +} diff --git a/server/lib/src/constants/groups.rs b/server/lib/src/migration_data/dl8/groups.rs similarity index 90% rename from server/lib/src/constants/groups.rs rename to server/lib/src/migration_data/dl8/groups.rs index 29b402414..0955f9009 100644 --- a/server/lib/src/constants/groups.rs +++ b/server/lib/src/migration_data/dl8/groups.rs @@ -106,7 +106,9 @@ lazy_static! { members: vec![], ..Default::default() }; +} +lazy_static! { // These are the "finer" roles. They encapsulate different concepts in the system. // The next section is the "system style" roles. These adjust the operation of // kanidm and relate to it's internals and how it functions. @@ -404,46 +406,3 @@ lazy_static! { ..Default::default() }; } - -/// Make a list of all the non-admin BuiltinGroup's that are created by default, doing it in a standard-ish way so we can use it around the platform -pub fn idm_builtin_non_admin_groups() -> Vec<&'static BuiltinGroup> { - // Create any system default schema entries. - vec![ - &BUILTIN_GROUP_DOMAIN_ADMINS, - &BUILTIN_GROUP_SCHEMA_ADMINS, - &BUILTIN_GROUP_ACCESS_CONTROL_ADMINS, - &BUILTIN_GROUP_UNIX_ADMINS, - &BUILTIN_GROUP_RECYCLE_BIN_ADMINS, - &BUILTIN_GROUP_SERVICE_DESK, - &BUILTIN_GROUP_OAUTH2_ADMINS, - &BUILTIN_GROUP_RADIUS_SERVICE_ADMINS, - &BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS, - &BUILTIN_GROUP_PEOPLE_ADMINS, - &BUILTIN_GROUP_PEOPLE_PII_READ, - &BUILTIN_GROUP_PEOPLE_ON_BOARDING, - &BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS, - &BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8, - &IDM_GROUP_ADMINS_V1, - &IDM_ALL_PERSONS, - &IDM_ALL_ACCOUNTS, - &BUILTIN_IDM_RADIUS_SERVERS_V1, - &BUILTIN_IDM_MAIL_SERVERS_DL8, - &BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7, - &IDM_PEOPLE_SELF_MAIL_WRITE_DL7, - &BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7, - &BUILTIN_GROUP_APPLICATION_ADMINS_DL8, - // Write deps on read, so write must be added first. - // All members must exist before we write HP - &IDM_HIGH_PRIVILEGE_DL8, - // other things - &IDM_UI_ENABLE_EXPERIMENTAL_FEATURES, - &IDM_ACCOUNT_MAIL_READ, - ] -} - -pub fn idm_builtin_admin_groups() -> Vec<&'static BuiltinGroup> { - vec![ - &BUILTIN_GROUP_SYSTEM_ADMINS_V1, - &BUILTIN_GROUP_IDM_ADMINS_V1, - ] -} diff --git a/server/lib/src/migration_data/dl8/key_providers.rs b/server/lib/src/migration_data/dl8/key_providers.rs new file mode 100644 index 000000000..f6cd2b3cf --- /dev/null +++ b/server/lib/src/migration_data/dl8/key_providers.rs @@ -0,0 +1,18 @@ +use crate::constants::entries::{Attribute, EntryClass}; +use crate::constants::uuids::UUID_KEY_PROVIDER_INTERNAL; +use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew}; +use crate::value::Value; + +lazy_static! { + pub static ref E_KEY_PROVIDER_INTERNAL_DL6: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::KeyProvider.to_value()), + (Attribute::Class, EntryClass::KeyProviderInternal.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_KEY_PROVIDER_INTERNAL)), + (Attribute::Name, Value::new_iname("key_provider_internal")), + ( + Attribute::Description, + Value::new_utf8s("The default database internal cryptographic key provider.") + ) + ); +} diff --git a/server/lib/src/migration_data/dl8/mod.rs b/server/lib/src/migration_data/dl8/mod.rs new file mode 100644 index 000000000..df1114e84 --- /dev/null +++ b/server/lib/src/migration_data/dl8/mod.rs @@ -0,0 +1,273 @@ +mod access; +mod accounts; +mod groups; +mod key_providers; +mod schema; +mod system_config; + +use self::access::*; +use self::accounts::*; +use self::groups::*; +use self::key_providers::*; +use self::schema::*; +use self::system_config::*; + +use crate::prelude::EntryInitNew; +use kanidm_proto::internal::OperationError; + +pub fn phase_1_schema_attrs() -> Vec { + vec![ + SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(), + SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(), + SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(), + SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(), + SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(), + SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(), + SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(), + SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(), + SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(), + SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(), + SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(), + SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(), + SCHEMA_ATTR_DOMAIN_NAME.clone().into(), + SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(), + SCHEMA_ATTR_DOMAIN_SSID.clone().into(), + SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(), + SCHEMA_ATTR_DOMAIN_UUID.clone().into(), + SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(), + SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(), + SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(), + SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(), + SCHEMA_ATTR_GIDNUMBER.clone().into(), + SCHEMA_ATTR_GRANT_UI_HINT.clone().into(), + SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(), + SCHEMA_ATTR_LOGINSHELL.clone().into(), + SCHEMA_ATTR_NAME_HISTORY.clone().into(), + SCHEMA_ATTR_NSUNIQUEID.clone().into(), + SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE + .clone() + .into(), + SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(), + SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(), + SCHEMA_ATTR_OAUTH2_SESSION.clone().into(), + SCHEMA_ATTR_PASSKEYS.clone().into(), + SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(), + SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(), + SCHEMA_ATTR_RADIUS_SECRET.clone().into(), + SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(), + SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(), + SCHEMA_ATTR_SYNC_COOKIE.clone().into(), + SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_UNIX_PASSWORD.clone().into(), + SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_DENIED_NAME.clone().into(), + SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(), + SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(), + // DL4 + SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(), + SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4 + .clone() + .into(), + // DL5 + // DL6 + SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(), + SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(), + SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(), + SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(), + // DL7 + SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(), + SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(), + SCHEMA_ATTR_REFERS_DL7.clone().into(), + SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(), + SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(), + SCHEMA_ATTR_MAIL_DL7.clone().into(), + SCHEMA_ATTR_LEGALNAME_DL7.clone().into(), + SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(), + // DL8 + SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(), + SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(), + SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(), + ] +} + +pub fn phase_2_schema_classes() -> Vec { + vec![ + SCHEMA_CLASS_DYNGROUP.clone().into(), + SCHEMA_CLASS_ORGPERSON.clone().into(), + SCHEMA_CLASS_POSIXACCOUNT.clone().into(), + SCHEMA_CLASS_POSIXGROUP.clone().into(), + SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(), + // DL4 + SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(), + // DL5 + // SCHEMA_CLASS_PERSON_DL5.clone().into(), + SCHEMA_CLASS_ACCOUNT_DL5.clone().into(), + // SCHEMA_CLASS_OAUTH2_RS_DL5.clone().into(), + SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(), + // DL6 + // SCHEMA_CLASS_ACCOUNT_POLICY_DL6.clone().into(), + // SCHEMA_CLASS_SERVICE_ACCOUNT_DL6.clone().into(), + // SCHEMA_CLASS_SYNC_ACCOUNT_DL6.clone().into(), + SCHEMA_CLASS_GROUP_DL6.clone().into(), + SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(), + SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(), + // SCHEMA_CLASS_DOMAIN_INFO_DL6.clone().into(), + // DL7 + // SCHEMA_CLASS_DOMAIN_INFO_DL7.clone().into(), + SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(), + SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(), + SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(), + SCHEMA_CLASS_OAUTH2_RS_DL7.clone().into(), + // DL8 + SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(), + SCHEMA_CLASS_APPLICATION_DL8.clone().into(), + SCHEMA_CLASS_PERSON_DL8.clone().into(), + SCHEMA_CLASS_DOMAIN_INFO_DL8.clone().into(), + ] +} + +pub fn phase_3_key_provider() -> Vec { + vec![E_KEY_PROVIDER_INTERNAL_DL6.clone()] +} + +pub fn phase_4_system_entries() -> Vec { + vec![ + E_SYSTEM_INFO_V1.clone(), + E_DOMAIN_INFO_DL6.clone(), + E_SYSTEM_CONFIG_V1.clone(), + ] +} + +pub fn phase_5_builtin_admin_entries() -> Result, OperationError> { + Ok(vec![ + BUILTIN_ACCOUNT_ADMIN.clone().into(), + BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(), + BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?, + BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?, + // We need to push anonymous *after* groups due to entry-managed-by + BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(), + ]) +} + +pub fn phase_6_builtin_non_admin_entries() -> Result, OperationError> { + Ok(vec![ + BUILTIN_GROUP_DOMAIN_ADMINS.clone().try_into()?, + BUILTIN_GROUP_SCHEMA_ADMINS.clone().try_into()?, + BUILTIN_GROUP_ACCESS_CONTROL_ADMINS.clone().try_into()?, + BUILTIN_GROUP_UNIX_ADMINS.clone().try_into()?, + BUILTIN_GROUP_RECYCLE_BIN_ADMINS.clone().try_into()?, + BUILTIN_GROUP_SERVICE_DESK.clone().try_into()?, + BUILTIN_GROUP_OAUTH2_ADMINS.clone().try_into()?, + BUILTIN_GROUP_RADIUS_SERVICE_ADMINS.clone().try_into()?, + BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_ADMINS.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_PII_READ.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_ON_BOARDING.clone().try_into()?, + BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS.clone().try_into()?, + BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8.clone().try_into()?, + IDM_GROUP_ADMINS_V1.clone().try_into()?, + IDM_ALL_PERSONS.clone().try_into()?, + IDM_ALL_ACCOUNTS.clone().try_into()?, + BUILTIN_IDM_RADIUS_SERVERS_V1.clone().try_into()?, + BUILTIN_IDM_MAIL_SERVERS_DL8.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7 + .clone() + .try_into()?, + IDM_PEOPLE_SELF_MAIL_WRITE_DL7.clone().try_into()?, + BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7 + .clone() + .try_into()?, + BUILTIN_GROUP_APPLICATION_ADMINS_DL8.clone().try_into()?, + // Write deps on read.clone().try_into()?, so write must be added first. + // All members must exist before we write HP + IDM_HIGH_PRIVILEGE_DL8.clone().try_into()?, + // other things + IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone().try_into()?, + IDM_ACCOUNT_MAIL_READ.clone().try_into()?, + ]) +} + +pub fn phase_7_builtin_access_control_profiles() -> Vec { + vec![ + // Built in access controls. + IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(), + IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(), + IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(), + IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(), + IDM_ACP_ACP_MANAGE_V1.clone().into(), + IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(), + IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(), + IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(), + IDM_ACP_RADIUS_SERVERS_V1.clone().into(), + IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(), + // IDM_ACP_SELF_READ_V1.clone(), + // IDM_ACP_SELF_WRITE_V1.clone(), + IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(), + // IDM_ACP_SELF_NAME_WRITE_V1.clone(), + IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(), + IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1 + .clone() + .into(), + IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(), + IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(), + IDM_ACP_GROUP_READ_V1.clone().into(), + IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(), + IDM_ACP_PEOPLE_PII_READ_V1.clone().into(), + IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_READ_V1.clone().into(), + IDM_ACP_PEOPLE_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_DELETE_V1.clone().into(), + IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), + IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 + .clone() + .into(), + IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 + .clone() + .into(), + IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(), + // DL4 + // DL5 + // IDM_ACP_OAUTH2_MANAGE_DL5.clone(), + // DL6 + // IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone(), + IDM_ACP_PEOPLE_CREATE_DL6.clone().into(), + IDM_ACP_GROUP_MANAGE_DL6.clone().into(), + IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(), + // IDM_ACP_DOMAIN_ADMIN_DL6.clone(), + // DL7 + // IDM_ACP_SELF_WRITE_DL7.clone(), + IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(), + IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(), + IDM_ACP_OAUTH2_MANAGE_DL7.clone().into(), + // DL8 + IDM_ACP_SELF_READ_DL8.clone().into(), + IDM_ACP_SELF_WRITE_DL8.clone().into(), + IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(), + IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(), + IDM_ACP_MAIL_SERVERS_DL8.clone().into(), + IDM_ACP_DOMAIN_ADMIN_DL8.clone().into(), + IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(), + ] +} diff --git a/server/lib/src/migration_data/dl8/schema.rs b/server/lib/src/migration_data/dl8/schema.rs new file mode 100644 index 000000000..1a3ebbca9 --- /dev/null +++ b/server/lib/src/migration_data/dl8/schema.rs @@ -0,0 +1,1506 @@ +//! Schema Entries +use crate::constants::entries::{Attribute, EntryClass}; +use crate::constants::uuids::*; +use crate::schema::{SchemaAttribute, SchemaClass}; +use crate::value::IndexType; +use crate::value::SyntaxType; + +lazy_static!( + +pub static ref SCHEMA_ATTR_DISPLAYNAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DISPLAYNAME, + name: Attribute::DisplayName, + description: "The publicly visible display name of this person".to_string(), + + index: vec![IndexType::Equality], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DISPLAYNAME_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DISPLAYNAME, + name: Attribute::DisplayName, + description: "The publicly visible display name of this person".to_string(), + + index: vec![IndexType::Equality, IndexType::SubString], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_MAIL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_MAIL, + name: Attribute::Mail, + description: "Mail addresses of the object".to_string(), + + index: vec![IndexType::Equality], + unique: true, + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::EmailAddress, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_MAIL_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_MAIL, + name: Attribute::Mail, + description: "Mail addresses of the object".to_string(), + + index: vec![IndexType::Equality, IndexType::SubString], + unique: true, + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::EmailAddress, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_EC_KEY_PRIVATE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_EC_KEY_PRIVATE, + name: Attribute::IdVerificationEcKey, + description: "Account verification private key".to_string(), + + index: vec![IndexType::Presence], + unique: false, + sync_allowed: false, + syntax: SyntaxType::EcKeyPrivate, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SSH_PUBLICKEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SSH_PUBLICKEY, + name: Attribute::SshPublicKey, + description: "SSH public keys of the object".to_string(), + + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::SshKey, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_PRIMARY_CREDENTIAL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PRIMARY_CREDENTIAL, + name: Attribute::PrimaryCredential, + description: "Primary credential material of the account for authentication interactively".to_string(), + + index: vec![IndexType::Presence], + sync_allowed: true, + syntax: SyntaxType::Credential, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LEGALNAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LEGALNAME, + name: Attribute::LegalName, + description: "The private and sensitive legal name of this person".to_string(), + + index: vec![IndexType::Equality], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LEGALNAME_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LEGALNAME, + name: Attribute::LegalName, + description: "The private and sensitive legal name of this person".to_string(), + + index: vec![IndexType::Equality, IndexType::SubString], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_NAME_HISTORY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_NAME_HISTORY, + name: Attribute::NameHistory, + description: "The history of names that a person has had".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::AuditLogString, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_RADIUS_SECRET: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_RADIUS_SECRET, + name: Attribute::RadiusSecret, + description: "The accounts generated radius secret for device network authentication".to_string(), + + sync_allowed: true, + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_NAME, + name: Attribute::DomainName, + description: "The domain's DNS name for webauthn and SPN generation purposes".to_string(), + + index: vec![IndexType::Equality, IndexType::Presence], + unique: true, + syntax: SyntaxType::Utf8StringIname, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND, + name: Attribute::LdapAllowUnixPwBind, + description: "Configuration to enable binds to LDAP objects using their UNIX password".to_string(), + + unique: false, + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_LDAP_BASEDN: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_LDAP_BASEDN, + name: Attribute::DomainLdapBasedn, + description: "The domain's optional ldap basedn. If unset defaults to domain components of domain name".to_string(), + + unique: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_DISPLAY_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_DISPLAY_NAME, + name: Attribute::DomainDisplayName, + description: "The user-facing display name of the Kanidm domain".to_string(), + + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_UUID: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_UUID, + name: Attribute::DomainUuid, + description: "The domain's uuid, used in CSN and trust relationships".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::Uuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_SSID: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_SSID, + name: Attribute::DomainSsid, + description: "The domains site-wide SSID for device autoconfiguration of wireless".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DENIED_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DENIED_NAME, + name: Attribute::DeniedName, + description: "Iname values that are not allowed to be used in 'name'.".to_string(), + + syntax: SyntaxType::Utf8StringIname, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DENIED_NAME_DL10: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DENIED_NAME, + name: Attribute::DeniedName, + description: "Iname values that are not allowed to be used in 'name'.".to_string(), + + syntax: SyntaxType::Utf8StringIname, + multivalue: true, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_TOKEN_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_TOKEN_KEY, + name: Attribute::DomainTokenKey, + description: "The domain token encryption private key (NOT USED)".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR, + name: Attribute::FernetPrivateKeyStr, + description: "The token encryption private key".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_GIDNUMBER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_GIDNUMBER, + name: Attribute::GidNumber, + description: "The groupid (uid) number of a group or account.to_string(). This is the same value as the UID number on posix accounts for security reasons".to_string(), + + index: vec![IndexType::Equality], + unique: true, + sync_allowed: true, + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_BADLIST_PASSWORD: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_BADLIST_PASSWORD, + name: Attribute::BadlistPassword, + description: "A password that is badlisted meaning that it can not be set as a valid password by any user account".to_string(), + + multivalue: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_AUTH_SESSION_EXPIRY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_AUTH_SESSION_EXPIRY, + name: Attribute::AuthSessionExpiry, + description: "An expiration time for an authentication session".to_string(), + + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY, + name: Attribute::PrivilegeExpiry, + description: "An expiration time for a privileged authentication session".to_string(), + + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH, + name: Attribute::AuthPasswordMinimumLength, + description: "Minimum length of passwords".to_string(), + + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LOGINSHELL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LOGINSHELL, + name: Attribute::LoginShell, + description: "A POSIX user's UNIX login shell".to_string(), + + sync_allowed: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_UNIX_PASSWORD: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_UNIX_PASSWORD, + name: Attribute::UnixPassword, + description: "A POSIX user's UNIX login password".to_string(), + + index: vec![IndexType::Presence], + syntax: SyntaxType::Credential, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_NSUNIQUEID: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_NSUNIQUEID, + name: Attribute::NsUniqueId, + description: "A unique id compatibility for 389-ds/dsee".to_string(), + + index: vec![IndexType::Equality], + unique: true, + sync_allowed: true, + syntax: SyntaxType::NsUniqueId, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ACCOUNT_EXPIRE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ACCOUNT_EXPIRE, + name: Attribute::AccountExpire, + description: "The datetime after which this account no longer may authenticate".to_string(), + + sync_allowed: true, + syntax: SyntaxType::DateTime, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ACCOUNT_VALID_FROM: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ACCOUNT_VALID_FROM, + name: Attribute::AccountValidFrom, + description: "The datetime after which this account may commence authenticating".to_string(), + + sync_allowed: true, + syntax: SyntaxType::DateTime, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST, + name: Attribute::WebauthnAttestationCaList, + description: "A set of CA's that limit devices that can be used with webauthn".to_string(), + + syntax: SyntaxType::WebauthnAttestationCaList, + multivalue: true, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_NAME, + name: Attribute::OAuth2RsName, + description: "The unique name of an external Oauth2 resource".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::Utf8StringIname, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_ORIGIN: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_ORIGIN, + name: Attribute::OAuth2RsOrigin, + description: "The origin domain of an oauth2 resource server".to_string(), + + syntax: SyntaxType::Url, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_ORIGIN, + name: Attribute::OAuth2RsOrigin, + description: "The origin domain of an OAuth2 client".to_string(), + + syntax: SyntaxType::Url, + multivalue: true, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING, + name: Attribute::OAuth2RsOriginLanding, + description: "The landing page of an RS, that will automatically trigger the auth process".to_string(), + + syntax: SyntaxType::Url, + ..Default::default() +}; + +// Introduced in DomainLevel4 +pub static ref SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT, + name: Attribute::OAuth2AllowLocalhostRedirect, + description: "Allow public clients associated to this RS to redirect to localhost".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP, + name: Attribute::OAuth2RsClaimMap, + description: "A set of custom claims mapped to group memberships of accounts".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + // CHANGE ME + syntax: SyntaxType::OauthClaimMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP, + name: Attribute::OAuth2RsScopeMap, + description: "A reference to a group mapped to scopes for the associated oauth2 resource server".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::OauthScopeMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP, + name: Attribute::OAuth2RsSupScopeMap, + description: "A reference to a group mapped to scopes for the associated oauth2 resource server".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::OauthScopeMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET, + name: Attribute::OAuth2RsBasicSecret, + description: "When using oauth2 basic authentication, the secret string of the resource server".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY, + name: Attribute::OAuth2RsTokenKey, + description: "An oauth2 resource servers unique token signing key".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES, + name: Attribute::OAuth2RsImplicitScopes, + description: "An oauth2 resource servers scopes that are implicitly granted to all users".to_string(), + + multivalue: true, + syntax: SyntaxType::OauthScope, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP, + name: Attribute::OAuth2ConsentScopeMap, + description: "A set of scopes mapped from a relying server to a user, where the user has previously consented to the following. If changed or deleted, consent will be re-sought".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::OauthScopeMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI, + name: Attribute::OAuth2StrictRedirectUri, + description: "Represents if strict redirect uri enforcement is enabled.".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + + +pub static ref SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE, + name: Attribute::OAuth2DeviceFlowEnable, + description: "Represents if OAuth2 Device Flow is permitted on this client.".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ES256_PRIVATE_KEY_DER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ES256_PRIVATE_KEY_DER, + name: Attribute::Es256PrivateKeyDer, + description: "An es256 private key".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_RS256_PRIVATE_KEY_DER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_RS256_PRIVATE_KEY_DER, + name: Attribute::Rs256PrivateKeyDer, + description: "An rs256 private key".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY, + name: Attribute::JwsEs256PrivateKey, + description: "An es256 private key for jws".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::JwsKeyEs256, + ..Default::default() +}; + +// TO BE REMOVED IN A FUTURE RELEASE +pub static ref SCHEMA_ATTR_PRIVATE_COOKIE_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PRIVATE_COOKIE_KEY, + name: Attribute::PrivateCookieKey, + description: "An private cookie hmac key".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE, + name: Attribute::OAuth2AllowInsecureClientDisablePkce, + description: "Allows disabling of PKCE for insecure OAuth2 clients".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE, + name: Attribute::OAuth2JwtLegacyCryptoEnable, + description: "Allows enabling legacy JWT cryptograhpy for clients".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN, + name: Attribute::CredentialUpdateIntentToken, + description: "The status of a credential update intent token".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::IntentToken, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_PASSKEYS: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PASSKEYS, + name: Attribute::PassKeys, + description: "A set of registered passkeys".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::Passkey, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ATTESTED_PASSKEYS: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ATTESTED_PASSKEYS, + name: Attribute::AttestedPasskeys, + description: "A set of registered device keys".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::AttestedPasskey, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DYNGROUP_FILTER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DYNGROUP_FILTER, + name: Attribute::DynGroupFilter, + description: "A filter describing the set of entries to add to a dynamic group".to_string(), + + syntax: SyntaxType::JsonFilter, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME, + name: Attribute::OAuth2PreferShortUsername, + description: "Use 'name' instead of 'spn' in the preferred_username claim".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_API_TOKEN_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_API_TOKEN_SESSION, + name: Attribute::ApiTokenSession, + description: "A session entry related to an issued API token".to_string(), + + index: vec![IndexType::Equality], + unique: true, + multivalue: true, + syntax: SyntaxType::ApiToken, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION, + name: Attribute::UserAuthTokenSession, + description: "A session entry related to an issued user auth token".to_string(), + + index: vec![IndexType::Equality], + unique: true, + multivalue: true, + syntax: SyntaxType::Session, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_SESSION, + name: Attribute::OAuth2Session, + description: "A session entry to an active oauth2 session, bound to a parent user auth token".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::Oauth2Session, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_TOKEN_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_TOKEN_SESSION, + name: Attribute::SyncTokenSession, + description: "A session entry related to an issued sync token".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::ApiToken, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_COOKIE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_COOKIE, + name: Attribute::SyncCookie, + description: "A private sync cookie for a remote IDM source".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_GRANT_UI_HINT: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_GRANT_UI_HINT, + name: Attribute::GrantUiHint, + description: "A UI hint that is granted via membership to a group".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::UiHint, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL, + name: Attribute::SyncCredentialPortal, + description: "The url of an external credential portal for synced accounts to visit to update their credentials".to_string(), + + syntax: SyntaxType::Url, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_YIELD_AUTHORITY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_YIELD_AUTHORITY, + name: Attribute::SyncYieldAuthority, + description: "A set of attributes that have their authority yielded to Kanidm in a sync agreement".to_string(), + + multivalue: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM, + name: Attribute::CredentialTypeMinimum, + description: "The minimum level of credential type that can satisfy this policy".to_string(), + + multivalue: false, + syntax: SyntaxType::CredentialType, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS, + name: Attribute::LimitSearchMaxResults, + description: "The maximum number of query results that may be returned in a single operation".to_string(), + + multivalue: false, + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST, + name: Attribute::LimitSearchMaxFilterTest, + description: "The maximum number of entries that may be examined in a partially indexed query".to_string(), + + multivalue: false, + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_INTERNAL_DATA, + name: Attribute::KeyInternalData, + description: "".to_string(), + multivalue: true, + syntax: SyntaxType::KeyInternal, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_PROVIDER_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_PROVIDER, + name: Attribute::KeyProvider, + description: "".to_string(), + multivalue: false, + syntax: SyntaxType::ReferenceUuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_ACTION_ROTATE, + name: Attribute::KeyActionRotate, + description: "".to_string(), + multivalue: false, + // Ephemeral action. + phantom: true, + syntax: SyntaxType::DateTime, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_ACTION_REVOKE, + name: Attribute::KeyActionRevoke, + description: "".to_string(), + multivalue: true, + // Ephemeral action. + phantom: true, + syntax: SyntaxType::HexString, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256, + name: Attribute::KeyActionImportJwsEs256, + description: "".to_string(), + multivalue: true, + // Ephemeral action. + phantom: true, + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_PATCH_LEVEL_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PATCH_LEVEL, + name: Attribute::PatchLevel, + description: "".to_string(), + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT, + name: Attribute::DomainDevelopmentTaint, + description: "A flag to show that the domain has been run on a development build, and will need additional work to upgrade/migrate.".to_string(), + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS, + name: Attribute::DomainAllowEasterEggs, + description: "A flag to enable easter eggs in the server that may not always be wanted by all users/deployments.".to_string(), + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_REFERS_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_REFERS, + name: Attribute::Refers, + description: "A reference to linked object".to_string(), + multivalue: false, + syntax: SyntaxType::ReferenceUuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LINKED_GROUP_DL8: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LINKED_GROUP, + name: Attribute::LinkedGroup, + description: "A reference linking a group to an entry".to_string(), + + multivalue: false, + syntax: SyntaxType::ReferenceUuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK, + name: Attribute::AllowPrimaryCredFallback, + description: "Allow fallback to primary password if no POSIX password exists".to_string(), + + multivalue: false, + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_CERTIFICATE_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_CERTIFICATE, + name: Attribute::Certificate, + description: "An x509 Certificate".to_string(), + multivalue: false, + syntax: SyntaxType::Certificate, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_APPLICATION_PASSWORD_DL8: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_APPLICATION_PASSWORD, + name: Attribute::ApplicationPassword, + description: "A set of application passwords".to_string(), + + multivalue: true, + syntax: SyntaxType::ApplicationPassword, + ..Default::default() +}; + +// === classes === + +pub static ref SCHEMA_CLASS_PERSON: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_PERSON, + name: EntryClass::Person.into(), + description: "Object representation of a person".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::Mail, + Attribute::LegalName, + ], + systemmust: vec![ + Attribute::DisplayName, + Attribute::Name, + Attribute::IdVerificationEcKey], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_PERSON_DL5: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_PERSON, + name: EntryClass::Person.into(), + description: "Object representation of a person".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::CredentialUpdateIntentToken, + Attribute::SshPublicKey, + Attribute::RadiusSecret, + Attribute::OAuth2ConsentScopeMap, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::Mail, + Attribute::LegalName, + ], + systemmust: vec![ + Attribute::IdVerificationEcKey + ], + systemexcludes: vec![EntryClass::ServiceAccount.into(), EntryClass::Application.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_PERSON_DL8: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_PERSON, + name: EntryClass::Person.into(), + description: "Object representation of a person".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::CredentialUpdateIntentToken, + Attribute::SshPublicKey, + Attribute::RadiusSecret, + Attribute::OAuth2ConsentScopeMap, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::Mail, + Attribute::LegalName, + Attribute::ApplicationPassword, + ], + systemmust: vec![ + Attribute::IdVerificationEcKey + ], + systemexcludes: vec![EntryClass::ServiceAccount.into(), EntryClass::Application.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ORGPERSON: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_ORGPERSON, + name: EntryClass::OrgPerson.into(), + description: "Object representation of an org person".to_string(), + + systemmay: vec![ + Attribute::LegalName + ], + systemmust: vec![ + Attribute::Mail, + Attribute::DisplayName, + Attribute::Name + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_GROUP_DL6: 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, + Attribute::GrantUiHint, + Attribute::Description, + Attribute::Mail, + ], + systemmust: vec![ + Attribute::Name, + Attribute::Spn], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DYNGROUP: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DYNGROUP, + name: EntryClass::DynGroup.into(), + description: "Object representation of a dynamic group".to_string(), + + systemmust: vec![Attribute::DynGroupFilter], + systemmay: vec![Attribute::DynMember], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT_POLICY_DL6: 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, + Attribute::PrivilegeExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT_POLICY_DL8: 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, + Attribute::PrivilegeExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_ACCOUNT, + name: EntryClass::Account.into(), + description: "Object representation of an account".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::CredentialUpdateIntentToken, + Attribute::SshPublicKey, + Attribute::RadiusSecret, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::Mail, + Attribute::OAuth2ConsentScopeMap, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::Description, + Attribute::NameHistory, + ], + systemmust: vec![ + Attribute::DisplayName, + Attribute::Name, + Attribute::Spn + ], + systemsupplements: vec![ + EntryClass::Person.into(), + EntryClass::ServiceAccount.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT_DL5: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_ACCOUNT, + name: EntryClass::Account.into(), + description: "Object representation of an account".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::NameHistory, + ], + systemmust: vec![ + Attribute::DisplayName, + Attribute::Name, + Attribute::Spn + ], + systemsupplements: vec![ + EntryClass::Person.into(), + EntryClass::ServiceAccount.into(), + EntryClass::OAuth2ResourceServer.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL6: 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, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::OAuth2ConsentScopeMap, + Attribute::Description, + + Attribute::Mail, + Attribute::PrimaryCredential, + Attribute::ApiTokenSession, + + Attribute::JwsEs256PrivateKey, + ], + systemexcludes: vec![EntryClass::Person.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL7: 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, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::OAuth2ConsentScopeMap, + Attribute::Description, + + Attribute::Mail, + Attribute::PrimaryCredential, + Attribute::ApiTokenSession, + ], + systemexcludes: vec![EntryClass::Person.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT, + name: EntryClass::SyncAccount.into(), + description: "Object representation of sync account".to_string(), + + systemmust: vec![Attribute::Name], + systemmay: vec![ + Attribute::SyncTokenSession, + Attribute::SyncCookie, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + Attribute::JwsEs256PrivateKey, + ], + systemexcludes: vec![EntryClass::Account.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT, + name: EntryClass::SyncAccount.into(), + description: "Object representation of sync account".to_string(), + + systemmust: vec![Attribute::Name], + systemmay: vec![ + Attribute::SyncTokenSession, + Attribute::SyncCookie, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + ], + systemexcludes: vec![EntryClass::Account.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::PrivateCookieKey, + Attribute::FernetPrivateKeyStr, + Attribute::Es256PrivateKeyDer, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL8: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::Image, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL9: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::Image, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + Attribute::DomainAllowEasterEggs, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL10: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::Image, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + Attribute::DomainAllowEasterEggs, + Attribute::DomainDisplayName, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_POSIXGROUP: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_POSIXGROUP, + name: EntryClass::PosixGroup.into(), + description: "Object representation of a posix group, requires group".to_string(), + + sync_allowed: true, + systemmust: vec![Attribute::GidNumber], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_POSIXACCOUNT: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_POSIXACCOUNT, + name: EntryClass::PosixAccount.into(), + description: "Object representation of a posix account, requires account".to_string(), + + sync_allowed: true, + systemmay: vec![Attribute::LoginShell, Attribute::UnixPassword], + systemmust: vec![Attribute::GidNumber], + systemsupplements: vec![Attribute::Account.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SYSTEM_CONFIG: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_SYSTEM_CONFIG, + name: EntryClass::SystemConfig.into(), + description: "The class representing a system (topologies) configuration options".to_string(), + + systemmay: vec![ + Attribute::Description, + Attribute::BadlistPassword, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + Attribute::DeniedName + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL4: 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, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2RsOriginLanding, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + ], + systemmust: vec![ + Attribute::OAuth2RsName, + Attribute::DisplayName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL5: 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, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2RsOriginLanding, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + Attribute::OAuth2Session, + ], + systemmust: vec![ + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS, + name: EntryClass::OAuth2ResourceServer.into(), + description: "The class representing a configured OAuth2 Client".to_string(), + + systemmay: vec![ + Attribute::Description, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2StrictRedirectUri, + ], + systemmust: vec![ + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL9: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS, + name: EntryClass::OAuth2ResourceServer.into(), + description: "The class representing a configured OAuth2 Client".to_string(), + + systemmay: vec![ + Attribute::Description, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + systemmust: vec![ + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC, + name: EntryClass::OAuth2ResourceServerBasic.into(), + description: "The class representing a configured OAuth2 client authenticated with HTTP basic authentication".to_string(), + + systemmay: vec![ + Attribute::OAuth2AllowInsecureClientDisablePkce, + ], + systemmust: vec![ Attribute::OAuth2RsBasicSecret], + systemexcludes: vec![ EntryClass::OAuth2ResourceServerPublic.into()], + ..Default::default() +}; + +// Introduced in DomainLevel4 +pub static ref SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_PUBLIC, + name: EntryClass::OAuth2ResourceServerPublic.into(), + description: "The class representing a configured Public OAuth2 Client with PKCE verification".to_string(), + + systemmay: vec![Attribute::OAuth2AllowLocalhostRedirect], + systemexcludes: vec![EntryClass::OAuth2ResourceServerBasic.into()], + ..Default::default() +}; + +// ========================================= +// KeyProviders + +pub static ref SCHEMA_CLASS_KEY_PROVIDER_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_PROVIDER, + name: EntryClass::KeyProvider.into(), + description: "A provider for cryptographic key storage and operations".to_string(), + systemmay: vec![ + Attribute::Description, + ], + systemmust: vec![ + Attribute::Name, + ], + systemsupplements: vec![ + EntryClass::KeyProviderInternal.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_PROVIDER_INTERNAL, + name: EntryClass::KeyProviderInternal.into(), + description: "The Kanidm internal cryptographic key provider".to_string(), + ..Default::default() +}; + +// ========================================= +// KeyObjects + +pub static ref SCHEMA_CLASS_KEY_OBJECT_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT, + name: EntryClass::KeyObject.into(), + description: "A cryptographic key object that can be used by a provider".to_string(), + systemmust: vec![ + Attribute::KeyProvider, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT_JWT_ES256, + name: EntryClass::KeyObjectJwtEs256.into(), + description: "A marker class indicating that this keyobject must provide jwt es256 capability.".to_string(), + systemsupplements: vec![ + EntryClass::KeyObject.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM, + name: EntryClass::KeyObjectJweA128GCM.into(), + description: "A marker class indicating that this keyobject must provide jwe aes-256-gcm capability.".to_string(), + systemsupplements: vec![ + EntryClass::KeyObject.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT_INTERNAL, + name: EntryClass::KeyObjectInternal.into(), + description: "A cryptographic key object that can be used by the internal provider".to_string(), + systemmay: vec![ + Attribute::KeyInternalData, + ], + systemsupplements: vec![ + EntryClass::KeyObject.into(), + ], + ..Default::default() +}; + +// ========================================= + +pub static ref SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_CLIENT_CERTIFICATE, + name: EntryClass::ClientCertificate.into(), + description: "A client authentication certificate".to_string(), + systemmay: vec![], + systemmust: vec![ + Attribute::Certificate, + Attribute::Refers, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_APPLICATION_DL8: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_APPLICATION, + name: EntryClass::Application.into(), + + description: "The class representing an application".to_string(), + systemmust: vec![Attribute::Name, Attribute::LinkedGroup], + systemmay: vec![Attribute::Description], + systemsupplements: vec![EntryClass::ServiceAccount.into()], + ..Default::default() +}; + +); diff --git a/server/lib/src/migration_data/dl8/system_config.rs b/server/lib/src/migration_data/dl8/system_config.rs new file mode 100644 index 000000000..107bd8bbe --- /dev/null +++ b/server/lib/src/migration_data/dl8/system_config.rs @@ -0,0 +1,1073 @@ +use crate::constants::uuids::*; + +use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew}; +use crate::prelude::{Attribute, EntryClass}; +use crate::value::Value; + +// Default entries for system_config +// This is separated because the password badlist section may become very long + +lazy_static! { + pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::SystemInfo.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_SYSTEM_INFO)), + ( + Attribute::Description, + Value::new_utf8s("System (local) info and metadata object.") + ), + (Attribute::Version, Value::Uint32(20)) + ); + pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::DomainInfo.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Class, EntryClass::KeyObject.to_value()), + (Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()), + (Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()), + (Attribute::Name, Value::new_iname("domain_local")), + (Attribute::Uuid, Value::Uuid(UUID_DOMAIN_INFO)), + ( + Attribute::Description, + Value::new_utf8s("This local domain's info and metadata object.") + ) + ); + pub static ref E_SYSTEM_CONFIG_V1: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::SystemConfig.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_SYSTEM_CONFIG)), + ( + Attribute::Description, + Value::new_utf8s("System (replicated) configuration options.") + ), + ( + Attribute::BadlistPassword, + Value::new_iutf8("bad@no3IBTyqHu$list") + ), + ( + Attribute::BadlistPassword, + Value::new_iutf8( + "demo_badlist_shohfie3aeci2oobur0aru9uushah6EiPi2woh4hohngoighaiRuepieN3ongoo1" + ) + ), + ( + Attribute::BadlistPassword, + Value::new_iutf8("100preteamare") + ), + (Attribute::BadlistPassword, Value::new_iutf8("14defebrero")), + (Attribute::BadlistPassword, Value::new_iutf8("1life1love")), + (Attribute::BadlistPassword, Value::new_iutf8("1life2live")), + (Attribute::BadlistPassword, Value::new_iutf8("1love1life")), + (Attribute::BadlistPassword, Value::new_iutf8("1love4life")), + (Attribute::BadlistPassword, Value::new_iutf8("212224236248")), + (Attribute::BadlistPassword, Value::new_iutf8("2813308004")), + ( + Attribute::BadlistPassword, + Value::new_iutf8("2fast2furious") + ), + (Attribute::BadlistPassword, Value::new_iutf8("2gether4ever")), + (Attribute::BadlistPassword, Value::new_iutf8("2pacshakur")), + ( + Attribute::BadlistPassword, + Value::new_iutf8("30secondstomars") + ), + (Attribute::BadlistPassword, Value::new_iutf8("3doorsdown")), + (Attribute::BadlistPassword, Value::new_iutf8("6cyclemind")), + ( + Attribute::BadlistPassword, + Value::new_iutf8("
), + EntryManager, +} + +#[derive(Clone, Debug, Default)] +/// Objects that are affected by the rules of this ACP. +pub enum BuiltinAcpTarget { + #[default] + None, + // Self, + Filter(ProtoFilter), + // MemberOf ( Uuid ), +} + +#[derive(Clone, Debug, Default)] +/// Built-in Access Control Profile definitions +pub struct BuiltinAcp { + classes: Vec, + pub name: &'static str, + uuid: Uuid, + description: &'static str, + receiver: BuiltinAcpReceiver, + target: BuiltinAcpTarget, + search_attrs: Vec, + modify_present_attrs: Vec, + modify_removed_attrs: Vec, + modify_classes: Vec, + create_classes: Vec, + create_attrs: Vec, +} + +impl From for EntryInitNew { + #[allow(clippy::panic)] + fn from(value: BuiltinAcp) -> Self { + let mut entry = EntryInitNew::default(); + + #[allow(clippy::panic)] + if value.name.is_empty() { + panic!("Builtin ACP has no name! {:?}", value); + } + #[allow(clippy::panic)] + if value.classes.is_empty() { + panic!("Builtin ACP has no classes! {:?}", value); + } + + value.classes.iter().for_each(|class| { + entry.add_ava(Attribute::Class, class.to_value()); + }); + + entry.set_ava(Attribute::Name, [Value::new_iname(value.name)]); + + if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { + panic!("Builtin ACP has invalid UUID! {:?}", value); + } + + entry.set_ava(Attribute::Uuid, [Value::Uuid(value.uuid)]); + entry.set_ava( + Attribute::Description, + [Value::new_utf8s(value.description)], + ); + + match &value.receiver { + #[allow(clippy::panic)] + BuiltinAcpReceiver::None => { + panic!("Builtin ACP has no receiver! {:?}", &value); + } + BuiltinAcpReceiver::Group(list) => { + entry.add_ava( + Attribute::Class, + EntryClass::AccessControlReceiverGroup.to_value(), + ); + for group in list { + entry.set_ava(Attribute::AcpReceiverGroup, [Value::Refer(*group)]); + } + } + BuiltinAcpReceiver::EntryManager => { + entry.add_ava( + Attribute::Class, + EntryClass::AccessControlReceiverEntryManager.to_value(), + ); + } + }; + + match &value.target { + #[allow(clippy::panic)] + BuiltinAcpTarget::None => { + panic!("Builtin ACP has no target! {:?}", &value); + } + BuiltinAcpTarget::Filter(proto_filter) => { + entry.add_ava( + Attribute::Class, + EntryClass::AccessControlTargetScope.to_value(), + ); + entry.set_ava( + Attribute::AcpTargetScope, + [Value::JsonFilt(proto_filter.clone())], + ); + } + } + + entry.set_ava( + Attribute::AcpSearchAttr, + value + .search_attrs + .into_iter() + .map(Value::from) + .collect::>(), + ); + value.modify_present_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpModifyPresentAttr, Value::from(attr)); + }); + value.modify_removed_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpModifyRemovedAttr, Value::from(attr)); + }); + value.modify_classes.into_iter().for_each(|class| { + entry.add_ava(Attribute::AcpModifyClass, Value::from(class)); + }); + value.create_classes.into_iter().for_each(|class| { + entry.add_ava(Attribute::AcpCreateClass, Value::from(class)); + }); + value.create_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpCreateAttr, Value::from(attr)); + }); + entry + } +} + +lazy_static! { + pub static ref IDM_ACP_RECYCLE_BIN_SEARCH_V1: BuiltinAcp = BuiltinAcp { + uuid: UUID_IDM_ACP_RECYCLE_BIN_SEARCH_V1, + name: "idm_acp_recycle_bin_search", + description: "Builtin IDM recycle bin search permission.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RECYCLE_BIN_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::Eq( + Attribute::Class.to_string(), + ATTR_RECYCLED.to_string() + )), + + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::LastModifiedCid, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_RECYCLE_BIN_REVIVE_V1: BuiltinAcp = BuiltinAcp { + uuid: UUID_IDM_ACP_RECYCLE_BIN_REVIVE_V1, + name: "idm_acp_recycle_bin_revive", + description: "Builtin IDM recycle bin revive permission.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RECYCLE_BIN_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::Eq( + Attribute::Class.to_string(), + ATTR_RECYCLED.to_string() + )), + modify_removed_attrs: vec![Attribute::Class], + modify_classes: vec![EntryClass::Recycled], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SCHEMA_WRITE_ATTRS_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_schema_write_attrs", + uuid: UUID_IDM_ACP_SCHEMA_WRITE_ATTRS_V1, + description: "Builtin IDM Control for management of schema attributes.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_SCHEMA_ADMINS] ), + // has a class, and isn't recycled/tombstoned + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + ProtoFilter::Eq(EntryClass::Class.to_string(),EntryClass::AttributeType.to_string()), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::AttributeName, + Attribute::Syntax, + Attribute::Uuid, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::Syntax, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::Syntax, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Index, + Attribute::Unique, + Attribute::MultiValue, + Attribute::AttributeName, + Attribute::Syntax, + Attribute::Uuid, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::AttributeType, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SCHEMA_WRITE_CLASSES_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_schema_write_classes", + uuid: UUID_IDM_ACP_SCHEMA_WRITE_CLASSES_V1, + description: "Builtin IDM Control for management of schema classes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SCHEMA_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + EntryClass::Class.to_string(), + EntryClass::ClassType.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::ClassName, + Attribute::Description, + Attribute::SystemMay, + Attribute::May, + Attribute::SystemMust, + Attribute::Must, + Attribute::Uuid, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::May, + Attribute::Must, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::May, + Attribute::Must, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::ClassName, + Attribute::Description, + Attribute::May, + Attribute::Must, + Attribute::Uuid, + ], + create_classes: vec![EntryClass::Object, EntryClass::ClassType,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACP_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_acp_manage", + uuid: UUID_IDM_ACP_ACP_MANAGE_V1, + description: "Builtin IDM Control for access profiles management.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCESS_CONTROL_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + EntryClass::Class.to_string(), + EntryClass::AccessControlProfile.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Description, + Attribute::AcpEnable, + Attribute::AcpReceiverGroup, + Attribute::AcpTargetScope, + Attribute::AcpSearchAttr, + Attribute::AcpModifyRemovedAttr, + Attribute::AcpModifyPresentAttr, + Attribute::AcpModifyClass, + Attribute::AcpCreateClass, + Attribute::AcpCreateAttr, + ], + modify_classes: vec![ + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + EntryClass::AccessControlModify, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + ], + create_classes: vec![ + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + EntryClass::AccessControlModify, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + ], + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_read", + uuid: UUID_IDM_ACP_GROUP_READ, + description: + "Builtin IDM Control for allowing all groups to be read by access control admins", + receiver: BuiltinAcpReceiver::Group(vec![ + UUID_IDM_ACCESS_CONTROL_ADMINS, + // UUID_IDM_SERVICE_DESK, + // UUID_IDM_PEOPLE_ADMINS, + ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::DynMember, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::Member, + Attribute::EntryManagedBy, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_entry_managed_by_modify", + uuid: UUID_IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY, + description: "Builtin IDM Control for allowing entry_managed_by to be set on group entries", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCESS_CONTROL_ADMINS]), + 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::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![Attribute::EntryManagedBy], + modify_present_attrs: vec![Attribute::EntryManagedBy], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6: 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), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + modify_classes: vec![EntryClass::AccountPolicy,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8: 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), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + modify_removed_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::AuthSessionExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::PrivilegeExpiry, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + modify_classes: vec![EntryClass::AccountPolicy,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL4: 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + 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::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL5: 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::Name, + Attribute::Spn, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Name, + Attribute::DisplayName, + Attribute::OAuth2RsName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL7: 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::Name, + Attribute::Spn, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Name, + Attribute::DisplayName, + Attribute::OAuth2RsName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_OAUTH2_MANAGE_DL9: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_oauth2_manage", + 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::Name, + Attribute::Spn, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsBasicSecret, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::DisplayName, + Attribute::Name, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Description, + Attribute::Name, + Attribute::DisplayName, + Attribute::OAuth2RsName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsSupScopeMap, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2AllowInsecureClientDisablePkce, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2AllowLocalhostRedirect, + Attribute::OAuth2RsClaimMap, + Attribute::Image, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::OAuth2ResourceServer, + EntryClass::OAuth2ResourceServerBasic, + EntryClass::OAuth2ResourceServerPublic, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_DOMAIN_ADMIN_DL6: 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, + // Grants read access to the key object. + // But this means we have to specify every type of key object? + // Future william problem ... + Attribute::KeyInternalData, + Attribute::LdapAllowUnixPwBind, + Attribute::Version, + ], + modify_removed_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + ], + modify_present_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_DOMAIN_ADMIN_DL8: 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::KeyInternalData, + Attribute::LdapAllowUnixPwBind, + Attribute::Version, + Attribute::Image, + ], + modify_removed_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + modify_present_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_DOMAIN_ADMIN_DL9: 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::DomainAllowEasterEggs, + Attribute::DomainDisplayName, + Attribute::DomainName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::DomainUuid, + Attribute::KeyInternalData, + Attribute::LdapAllowUnixPwBind, + Attribute::Version, + Attribute::Image, + ], + modify_removed_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::DomainAllowEasterEggs, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + modify_present_attrs: vec![ + Attribute::DomainDisplayName, + Attribute::DomainLdapBasedn, + Attribute::DomainSsid, + Attribute::DomainAllowEasterEggs, + Attribute::LdapAllowUnixPwBind, + Attribute::KeyActionRevoke, + Attribute::KeyActionRotate, + Attribute::Image, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SYNC_ACCOUNT_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_sync_account_manage", + uuid: UUID_IDM_ACP_SYNC_ACCOUNT_MANAGE_V1, + description: "Builtin IDM Control for managing IDM synchronisation accounts / connections", + receiver: BuiltinAcpReceiver::Group(vec![UUID_DOMAIN_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + Attribute::Class.to_string(), + EntryClass::SyncAccount.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Description, + Attribute::JwsEs256PrivateKey, + Attribute::SyncTokenSession, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + Attribute::SyncCookie, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::JwsEs256PrivateKey, + Attribute::SyncTokenSession, + Attribute::SyncCredentialPortal, + Attribute::SyncCookie, + Attribute::SyncYieldAuthority, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::SyncTokenSession, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + ], + create_attrs: vec![Attribute::Class, Attribute::Name, Attribute::Description,], + create_classes: vec![EntryClass::Object, EntryClass::SyncAccount,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_ENTRY_MANAGER_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_entry_manager", + uuid: UUID_IDM_ACP_GROUP_ENTRY_MANAGER_V1, + description: "Builtin IDM Control for allowing EntryManager to read and modify groups", + receiver: BuiltinAcpReceiver::EntryManager, + // Any group + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Uuid, + Attribute::Description, + Attribute::Member, + Attribute::DynMember, + Attribute::EntryManagedBy, + ], + modify_present_attrs: vec![ + Attribute::Description, + Attribute::Member, + ], + modify_removed_attrs: vec![ + Attribute::Description, + Attribute::Member, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_RADIUS_SERVERS_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_radius_servers", + uuid: UUID_IDM_ACP_RADIUS_SERVERS_V1, + description: + "Builtin IDM Control for RADIUS servers to read credentials and other needed details.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RADIUS_SERVERS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Pres(EntryClass::Class.to_string()), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::RadiusSecret, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_RADIUS_SECRET_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_radius_secret_manage", + uuid: UUID_IDM_ACP_RADIUS_SECRET_MANAGE_V1, + description: "Builtin IDM Control allowing reads and writes to user radius secrets.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_RADIUS_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![Attribute::RadiusSecret], + modify_present_attrs: vec![Attribute::RadiusSecret], + modify_removed_attrs: vec![Attribute::RadiusSecret], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_MAIL_SERVERS_DL8: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_mail_servers", + uuid: UUID_IDM_ACP_MAIL_SERVERS, + description: + "Builtin IDM Control for MAIL servers to read email addresses and other needed attributes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_MAIL_SERVERS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::Group), + ]), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::DisplayName, + Attribute::Mail, + Attribute::Member, + Attribute::DynMember, + Attribute::MemberOf, + Attribute::GidNumber, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + name: "idm_acp_people_self_write_mail", + uuid: UUID_IDM_ACP_PEOPLE_SELF_WRITE_MAIL, + description: "Builtin IDM Control for self write of mail for people accounts.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_SELF_MAIL_WRITE]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + match_class_filter!(EntryClass::Account).clone(), + ProtoFilter::SelfUuid, + ])), + modify_removed_attrs: vec![Attribute::Mail], + modify_present_attrs: vec![Attribute::Mail], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_READ_V1: BuiltinAcp = BuiltinAcp { + name: "idm_acp_self_read", + uuid: UUID_IDM_ACP_SELF_READ, + description: + "Builtin IDM Control for self read - required for whoami and many other functions", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ALL_ACCOUNTS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Class, + Attribute::MemberOf, + Attribute::Mail, + Attribute::RadiusSecret, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::Uuid, + Attribute::SyncParentUuid, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PrimaryCredential, + Attribute::UserAuthTokenSession, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_READ_DL8: BuiltinAcp = BuiltinAcp { + name: "idm_acp_self_read", + uuid: UUID_IDM_ACP_SELF_READ, + description: + "Builtin IDM Control for self read - required for whoami and many other functions", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ALL_ACCOUNTS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Class, + Attribute::MemberOf, + Attribute::Mail, + Attribute::RadiusSecret, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::Uuid, + Attribute::SyncParentUuid, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PrimaryCredential, + Attribute::UserAuthTokenSession, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::ApplicationPassword, + Attribute::SshPublicKey, + Attribute::UnixPassword, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_WRITE_V1: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_write", + uuid: UUID_IDM_ACP_SELF_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write - required for people to update their own identities and credentials in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::DisplayName, + Attribute::LegalName, + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::UserAuthTokenSession, + Attribute::ApplicationPassword, + ], + modify_present_attrs: vec![ + Attribute::DisplayName, + Attribute::LegalName, + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::ApplicationPassword, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_WRITE_DL7: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_write", + uuid: UUID_IDM_ACP_SELF_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write - required for people to update their own credentials in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::UserAuthTokenSession, + ], + modify_present_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_WRITE_DL8: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_write", + uuid: UUID_IDM_ACP_SELF_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write - required for people to update their own credentials in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::UserAuthTokenSession, + Attribute::ApplicationPassword, + ], + modify_present_attrs: vec![ + Attribute::RadiusSecret, + Attribute::PrimaryCredential, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::ApplicationPassword, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_NAME_WRITE_V1: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_name_write", + uuid: UUID_IDM_ACP_SELF_NAME_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write of name - required for people to update their own identities in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_PERSONS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::Name, + ], + modify_present_attrs: vec![ + Attribute::Name, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SELF_NAME_WRITE_DL7: BuiltinAcp = BuiltinAcp{ + name: "idm_acp_self_name_write", + uuid: UUID_IDM_ACP_SELF_NAME_WRITE_V1, + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + description: "Builtin IDM Control for self write of name - required for people to update their own identities in line with best practices.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_PEOPLE_SELF_NAME_WRITE] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::SelfUuid, + match_class_filter!(EntryClass::Person).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACCOUNT_SELF_WRITE_V1: BuiltinAcp = BuiltinAcp { + name: "idm_acp_account_self_write", + uuid: UUID_IDM_ACP_ACCOUNT_SELF_WRITE_V1, + description: "Builtin IDM Control for self write - required for accounts to update their own session state.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify + ], + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_ACCOUNTS] ), + target: BuiltinAcpTarget::Filter(ProtoFilter::SelfUuid), + modify_removed_attrs: vec![ + Attribute::UserAuthTokenSession + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_all_accounts_posix_read", + uuid: UUID_IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1, + description: + "Builtin IDM Control for reading minimal posix attrs - applies anonymous and all authenticated accounts.", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_ALL_ACCOUNTS] ), + target: BuiltinAcpTarget::Filter( ProtoFilter::And( + vec![ + ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::Group), + ]), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ] + )), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::DisplayName, + Attribute::Class, + Attribute::MemberOf, + Attribute::Member, + Attribute::DynMember, + Attribute::Uuid, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::SshPublicKey, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACCOUNT_MAIL_READ_DL6: 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 and group mail attributes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_MAIL_READ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Or(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::Group), + ]), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![Attribute::Mail], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_system_config_account_policy_manage", + uuid: UUID_IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1, + description: "Builtin IDM Control for granting system configuration of account policy", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_POLICY_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + Attribute::Uuid.to_string(), + STR_UUID_SYSTEM_CONFIG.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Description, + Attribute::BadlistPassword, + Attribute::DeniedName, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + Attribute::Version, + ], + modify_removed_attrs: vec![ + Attribute::BadlistPassword, + Attribute::DeniedName, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + ], + modify_present_attrs: vec![ + Attribute::BadlistPassword, + Attribute::DeniedName, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_HP_GROUP_UNIX_MANAGE_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_group_unix_manage", + uuid: UUID_IDM_ACP_HP_GROUP_UNIX_MANAGE_V1, + description: "Builtin IDM Control for managing and extending high privilege groups with unix attributes", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_UNIX_ADMINS] ), + // HP group, not Recycled/Tombstone + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_HP.clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::DynMember, + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::Member, + Attribute::GidNumber, + ], + modify_removed_attrs: vec![ + Attribute::GidNumber, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::GidNumber, + ], + modify_classes: vec![ + EntryClass::PosixGroup, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_MANAGE_DL6: 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::Mail, + Attribute::Member, + Attribute::DynMember, + Attribute::EntryManagedBy, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Group, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_MANAGE_DL9: 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::Mail, + Attribute::Member, + Attribute::DynMember, + Attribute::EntryManagedBy, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Group, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::Mail, + Attribute::Member, + Attribute::EntryManagedBy, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_GROUP_UNIX_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_group_unix_manage", + uuid: UUID_IDM_ACP_GROUP_UNIX_MANAGE_V1, + description: "Builtin IDM Control for managing unix groups", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_UNIX_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Group), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + search_attrs: vec![ + Attribute::DynMember, + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::Member, + Attribute::GidNumber, + ], + modify_removed_attrs: vec![Attribute::GidNumber,], + modify_present_attrs: vec![Attribute::Class, Attribute::GidNumber,], + modify_classes: vec![EntryClass::PosixGroup,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_ACCOUNT_UNIX_EXTEND_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_account_unix_extend", + uuid: UUID_IDM_ACP_ACCOUNT_UNIX_EXTEND_V1, + description: "Builtin IDM Control for managing and extending unix accounts", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_UNIX_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::Description, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::SshPublicKey, + ], + modify_removed_attrs: vec![ + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::SshPublicKey, + ], + modify_present_attrs: vec![ + Attribute::Class, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::SshPublicKey, + ], + modify_classes: vec![EntryClass::PosixAccount,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_PII_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_people_pii_read", + uuid: UUID_IDM_ACP_PEOPLE_PII_READ_V1, + description: "Builtin IDM Control for reading personal and sensitive data.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS, UUID_IDM_PEOPLE_PII_READ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Uuid, + Attribute::Spn, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Mail, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_PII_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify + ], + name: "idm_acp_people_pii_manage", + uuid: UUID_IDM_ACP_PEOPLE_PII_MANAGE_V1, + description: "Builtin IDM Control for modifying peoples personal and sensitive data", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Mail, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::LegalName, + Attribute::Mail, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_CREATE_DL6: 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::Uuid, + Attribute::Name, + Attribute::DisplayName, + Attribute::Mail, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + ], + create_classes: vec![EntryClass::Object, EntryClass::Account, EntryClass::Person,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_PEOPLE_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + name: "idm_acp_people_manage", + uuid: UUID_IDM_ACP_PEOPLE_MANAGE_V1, + description: "Builtin IDM Control for management of peoples non sensitive attributes.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + modify_removed_attrs: vec![Attribute::AccountExpire, Attribute::AccountValidFrom,], + modify_present_attrs: vec![Attribute::AccountExpire, Attribute::AccountValidFrom,], + ..Default::default() + }; +} + +// Person Read +lazy_static! { + pub static ref IDM_ACP_PEOPLE_READ_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlSearch, + ], + name: "idm_acp_people_read", + uuid: UUID_IDM_ACP_PEOPLE_READ_V1, + description: "Builtin IDM Control for reading non-sensitive data.", + receiver: BuiltinAcpReceiver::Group(vec![ + UUID_IDM_PEOPLE_ADMINS, + UUID_IDM_PEOPLE_PII_READ, + UUID_IDM_ACCOUNT_MAIL_READ, + UUID_IDM_SERVICE_DESK + ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::DisplayName, + Attribute::MemberOf, + Attribute::Uuid, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + ], + ..Default::default() + }; +} + +// Person Delete +lazy_static! { + pub static ref IDM_ACP_PEOPLE_DELETE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlDelete, + ], + name: "idm_acp_people_delete", + uuid: UUID_IDM_ACP_PEOPLE_DELETE_V1, + description: "Builtin IDM Control for deleting persons.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS,]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + ..Default::default() + }; +} + +// Person Account Credential Reset +lazy_static! { + pub static ref IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_people_credential_reset", + uuid: UUID_IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1, + description: "Builtin IDM Control for resetting peoples credentials ", + receiver: BuiltinAcpReceiver::Group(vec![ + UUID_IDM_PEOPLE_ADMINS, + UUID_IDM_SERVICE_DESK, + UUID_IDM_PEOPLE_ON_BOARDING, + ]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + match_class_filter!(EntryClass::Account), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Spn, + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_removed_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_present_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +// HP Person Account Credential Reset +lazy_static! { + pub static ref IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_people_credential_reset", + uuid: UUID_IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1, + description: "Builtin IDM Control for resetting high privilege peoples credentials ", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_PEOPLE_ADMINS,]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Person), + match_class_filter!(EntryClass::Account), + FILTER_HP.clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Spn, + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_removed_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + modify_present_attrs: vec![ + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + ], + ..Default::default() + }; +} + +// Service Account Create/Manage +// needs to be able to assign to entry managed by +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_CREATE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + ], + name: "idm_acp_service_account_create", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_CREATE_V1, + description: "Builtin IDM Control for creating new service accounts.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + create_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::DisplayName, + Attribute::EntryManagedBy, + Attribute::Description, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::ServiceAccount, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify + ], + name: "idm_acp_service_account_manage", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1, + description: "Builtin IDM Control for modifying service account data", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::DisplayName, + Attribute::Mail, + Attribute::SshPublicKey, + Attribute::UnixPassword, + Attribute::PrimaryCredential, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + ], + modify_present_attrs: vec![Attribute::Name, Attribute::DisplayName, Attribute::Mail,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_DELETE_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlDelete, + ], + name: "idm_acp_service_account_delete", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_DELETE_V1, + description: "Builtin IDM Control for deleting service accounts.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + ..Default::default() + }; +} + +// Service Account Credential Manage +// entry managed by? + +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_service_account_entry_manager", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1, + description: "Builtin IDM Control for allowing entry managers to modify service accounts", + receiver: BuiltinAcpReceiver::EntryManager, + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Account), + match_class_filter!(EntryClass::ServiceAccount), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + Attribute::DisplayName, + Attribute::SshPublicKey, + Attribute::GidNumber, + Attribute::LoginShell, + Attribute::UnixPassword, + Attribute::PassKeys, + Attribute::PrimaryCredential, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + ], + modify_removed_attrs: vec![ + Attribute::DisplayName, + Attribute::SshPublicKey, + Attribute::PrimaryCredential, + Attribute::UnixPassword, + // For legacy upgrades we allow removing this. + Attribute::PassKeys, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + ], + modify_present_attrs: vec![ + Attribute::DisplayName, + Attribute::SshPublicKey, + Attribute::PrimaryCredential, + // Should this be a thing? I think no? + // Attribute::UnixPassword, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::ApiTokenSession, + ], + ..Default::default() + }; +} + +// Service Account Access Manager +lazy_static! { + pub static ref IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_service_account_entry_managed_by_modify", + uuid: UUID_IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY, + description: + "Builtin IDM Control for allowing entry_managed_by to be set on service account entries", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_SERVICE_ACCOUNT_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_ANDNOT_HP_OR_RECYCLED_OR_TOMBSTONE.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![Attribute::EntryManagedBy], + modify_present_attrs: vec![Attribute::EntryManagedBy], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_service_account_entry_managed_by", + uuid: UUID_IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY, + description: "Builtin IDM Control for allowing entry_managed_by to be set on high priv service account entries", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCESS_CONTROL_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + match_class_filter!(EntryClass::ServiceAccount).clone(), + match_class_filter!(EntryClass::Account).clone(), + FILTER_HP.clone(), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(), + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Name, + Attribute::Spn, + Attribute::Uuid, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![Attribute::EntryManagedBy], + modify_present_attrs: vec![Attribute::EntryManagedBy], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_hp_client_certificate_manager", + uuid: UUID_IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER, + description: "Builtin IDM Control for allowing client certificate management.", + receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_CLIENT_CERTIFICATE_ADMINS]), + target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![ + ProtoFilter::Eq( + EntryClass::Class.to_string(), + EntryClass::ClientCertificate.to_string() + ), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Certificate, + Attribute::Refers, + ], + modify_removed_attrs: vec![Attribute::Certificate, Attribute::Refers,], + modify_present_attrs: vec![Attribute::Certificate, Attribute::Refers,], + create_attrs: vec![Attribute::Class, Attribute::Certificate, Attribute::Refers,], + create_classes: vec![EntryClass::Object, EntryClass::ClientCertificate,], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_APPLICATION_MANAGE_DL8: BuiltinAcp = BuiltinAcp{ + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlCreate, + EntryClass::AccessControlDelete, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_application_manage", + uuid: UUID_IDM_ACP_APPLICATION_MANAGE, + description: "Builtin IDM Control for creating and deleting applications in the directory", + receiver: BuiltinAcpReceiver::Group ( vec![UUID_IDM_APPLICATION_ADMINS] ), + // Any application + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Application), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + create_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + create_classes: vec![ + EntryClass::Object, + EntryClass::Account, + EntryClass::ServiceAccount, + EntryClass::Application, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + ..Default::default() + }; +} + +lazy_static! { + pub static ref IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8: BuiltinAcp = BuiltinAcp { + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + EntryClass::AccessControlSearch + ], + name: "idm_acp_application_entry_manager", + uuid: UUID_IDM_ACP_APPLICATION_ENTRY_MANAGER, + description: "Builtin IDM Control for allowing EntryManager to read and modify applications", + receiver: BuiltinAcpReceiver::EntryManager, + // Applications that belong to the Entry Manager. + target: BuiltinAcpTarget::Filter( ProtoFilter::And(vec![ + match_class_filter!(EntryClass::Application), + FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone() + ])), + search_attrs: vec![ + Attribute::Class, + Attribute::Uuid, + Attribute::Name, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::Description, + Attribute::LinkedGroup, + Attribute::EntryManagedBy, + ], + modify_present_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::LinkedGroup, + ], + modify_removed_attrs: vec![ + Attribute::Name, + Attribute::Description, + Attribute::DisplayName, + Attribute::Mail, + Attribute::UnixPassword, + Attribute::ApiTokenSession, + Attribute::UserAuthTokenSession, + Attribute::LinkedGroup, + ], + ..Default::default() + }; +} diff --git a/server/lib/src/migration_data/dl9/accounts.rs b/server/lib/src/migration_data/dl9/accounts.rs new file mode 100644 index 000000000..f7b6a065a --- /dev/null +++ b/server/lib/src/migration_data/dl9/accounts.rs @@ -0,0 +1,35 @@ +//! Constant Entries for the IDM +use crate::constants::uuids::*; +use crate::migration_data::types::BuiltinAccount; +use kanidm_proto::v1::AccountType; + +lazy_static! { + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "idm_admin", + uuid: UUID_IDM_ADMIN, + description: "Builtin IDM Admin account.", + displayname: "IDM Administrator", + }; + + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "admin", + uuid: UUID_ADMIN, + description: "Builtin System Admin account.", + displayname: "System Administrator", + }; + + pub static ref BUILTIN_ACCOUNT_ANONYMOUS_DL6: BuiltinAccount = BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: Some(UUID_IDM_ADMINS), + name: "anonymous", + uuid: UUID_ANONYMOUS, + description: "Anonymous access account.", + displayname: "Anonymous", + }; +} diff --git a/server/lib/src/migration_data/dl9/groups.rs b/server/lib/src/migration_data/dl9/groups.rs new file mode 100644 index 000000000..0955f9009 --- /dev/null +++ b/server/lib/src/migration_data/dl9/groups.rs @@ -0,0 +1,408 @@ +use crate::entry::EntryInitNew; +use crate::prelude::*; +use crate::value::CredentialType; + +use kanidm_proto::internal::{Filter, OperationError, UiHint}; + +#[derive(Clone, Debug, Default)] +/// Built-in group definitions +pub struct BuiltinGroup { + pub name: &'static str, + pub description: &'static str, + pub uuid: uuid::Uuid, + pub members: Vec, + pub entry_managed_by: Option, + pub dyngroup: bool, + pub dyngroup_filter: Option, + pub extra_attributes: Vec<(Attribute, Value)>, +} + +impl TryFrom for EntryInitNew { + type Error = OperationError; + + fn try_from(val: BuiltinGroup) -> Result { + let mut entry = EntryInitNew::new(); + + if val.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { + error!("Builtin ACP has invalid UUID! {:?}", val); + return Err(OperationError::InvalidUuid); + } + + entry.add_ava(Attribute::Name, Value::new_iname(val.name)); + entry.add_ava(Attribute::Description, Value::new_utf8s(val.description)); + // classes for groups + entry.set_ava( + Attribute::Class, + vec![EntryClass::Group.into(), EntryClass::Object.into()], + ); + if val.dyngroup { + if !val.members.is_empty() { + return Err(OperationError::InvalidSchemaState(format!( + "Builtin dyngroup {} has members specified, this is not allowed", + val.name + ))); + } + entry.add_ava(Attribute::Class, EntryClass::DynGroup.to_value()); + match val.dyngroup_filter { + Some(filter) => entry.add_ava(Attribute::DynGroupFilter, Value::JsonFilt(filter)), + None => { + error!( + "No filter specified for dyngroup '{}' this is going to break things!", + val.name + ); + return Err(OperationError::FilterGeneration); + } + }; + } + + if let Some(entry_manager) = val.entry_managed_by { + entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager)); + } + + entry.add_ava(Attribute::Uuid, Value::Uuid(val.uuid)); + entry.set_ava( + Attribute::Member, + val.members + .into_iter() + .map(Value::Refer) + .collect::>(), + ); + // add any extra attributes + val.extra_attributes + .into_iter() + .for_each(|(attr, val)| entry.add_ava(attr, val)); + // all done! + Ok(entry) + } +} + +lazy_static! { + // There are our built in "roles". They encapsulate some higher level collections + // of roles. The intent is to allow a pretty generic and correct by default set + // of these use cases. + pub static ref BUILTIN_GROUP_SYSTEM_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: "system_admins", + description: "Builtin System Administrators Group.", + uuid: UUID_SYSTEM_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_ADMIN], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_IDM_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_admins", + description: "Builtin IDM Administrators Group.", + uuid: UUID_IDM_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMIN], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SERVICE_DESK: BuiltinGroup = BuiltinGroup { + name: "idm_service_desk", + description: "Builtin Service Desk Group.", + uuid: UUID_IDM_SERVICE_DESK, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![], + ..Default::default() + }; +} + +lazy_static! { + // These are the "finer" roles. They encapsulate different concepts in the system. + // The next section is the "system style" roles. These adjust the operation of + // kanidm and relate to it's internals and how it functions. + pub static ref BUILTIN_GROUP_RECYCLE_BIN_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_recycle_bin_admins", + description: "Builtin Recycle Bin Administrators Group.", + uuid: UUID_IDM_RECYCLE_BIN_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for granting local domain administration rights and trust administration rights + pub static ref BUILTIN_GROUP_DOMAIN_ADMINS: BuiltinGroup = BuiltinGroup { + name: "domain_admins", + description: "Builtin IDM Group for granting local domain administration rights and trust administration rights.", + uuid: UUID_DOMAIN_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SCHEMA_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_schema_admins", + description: "Builtin Schema Administration Group.", + uuid: UUID_IDM_SCHEMA_ADMINS, + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_ACCESS_CONTROL_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_access_control_admins", + description: "Builtin Access Control Administration Group.", + entry_managed_by: Some(UUID_SYSTEM_ADMINS), + uuid: UUID_IDM_ACCESS_CONTROL_ADMINS, + members: vec![UUID_SYSTEM_ADMINS], + ..Default::default() + }; + + // These are the IDM roles. They concern application integration, user permissions + // and credential security management. + + /// Builtin IDM Group for managing persons and their account details + pub static ref BUILTIN_GROUP_PEOPLE_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_people_admins", + description: "Builtin People Administration Group.", + uuid: UUID_IDM_PEOPLE_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_PEOPLE_ON_BOARDING: BuiltinGroup = BuiltinGroup { + name: "idm_people_on_boarding", + description: "Builtin People On Boarding Group.", + uuid: UUID_IDM_PEOPLE_ON_BOARDING, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![], + ..Default::default() + }; + + /// Builtin IDM Group for granting elevated people (personal data) read permissions. + pub static ref BUILTIN_GROUP_PEOPLE_PII_READ: BuiltinGroup = BuiltinGroup { + name: "idm_people_pii_read", + description: "Builtin IDM Group for granting elevated people (personal data) read permissions.", + uuid: UUID_IDM_PEOPLE_PII_READ, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![], + ..Default::default() + }; + + /// Builtin IDM Group for granting people the ability to write to their own name attributes. + pub static ref BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7: BuiltinGroup = BuiltinGroup { + name: "idm_people_self_name_write", + description: "Builtin IDM Group denoting users that can write to their own name attributes.", + uuid: UUID_IDM_PEOPLE_SELF_NAME_WRITE, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![ + UUID_IDM_ALL_PERSONS + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_service_account_admins", + description: "Builtin Service Account Administration Group.", + uuid: UUID_IDM_SERVICE_ACCOUNT_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain. + pub static ref BUILTIN_GROUP_OAUTH2_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_oauth2_admins", + description: "Builtin Oauth2 Integration Administration Group.", + uuid: UUID_IDM_OAUTH2_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_RADIUS_SERVICE_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_radius_service_admins", + description: "Builtin Radius Administration Group.", + uuid: UUID_IDM_RADIUS_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for RADIUS server access delegation. + pub static ref BUILTIN_IDM_RADIUS_SERVERS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_radius_servers", + description: "Builtin IDM Group for RADIUS server access delegation.", + uuid: UUID_IDM_RADIUS_SERVERS, + entry_managed_by: Some(UUID_IDM_RADIUS_ADMINS), + members: vec![ + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_mail_service_admins", + description: "Builtin Mail Server Administration Group.", + uuid: UUID_IDM_MAIL_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for MAIL server Access delegation. + pub static ref BUILTIN_IDM_MAIL_SERVERS_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_mail_servers", + description: "Builtin IDM Group for MAIL server access delegation.", + uuid: UUID_IDM_MAIL_SERVERS, + entry_managed_by: Some(UUID_IDM_MAIL_ADMINS), + members: vec![ + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_account_policy_admins", + description: "Builtin Account Policy Administration Group.", + uuid: UUID_IDM_ACCOUNT_POLICY_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for managing posix/unix attributes on groups and users. + pub static ref BUILTIN_GROUP_UNIX_ADMINS: BuiltinGroup = BuiltinGroup { + name: "idm_unix_admins", + description: "Builtin Unix Administration Group.", + uuid: UUID_IDM_UNIX_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for managing client authentication certificates. + pub static ref BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7: BuiltinGroup = BuiltinGroup { + name: "idm_client_certificate_admins", + description: "Builtin Client Certificate Administration Group.", + uuid: UUID_IDM_CLIENT_CERTIFICATE_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Builtin IDM Group for granting elevated group write and lifecycle permissions. + pub static ref IDM_GROUP_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_group_admins", + description: "Builtin IDM Group for granting elevated group write and lifecycle permissions.", + uuid: UUID_IDM_GROUP_ADMINS, + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; + + /// Self-write of mail + pub static ref IDM_PEOPLE_SELF_MAIL_WRITE_DL7: BuiltinGroup = BuiltinGroup { + name: "idm_people_self_mail_write", + description: "Builtin IDM Group for people accounts to update their own mail.", + uuid: UUID_IDM_PEOPLE_SELF_MAIL_WRITE, + members: Vec::with_capacity(0), + ..Default::default() + }; +} + +// at some point vs code just gives up on syntax highlighting inside lazy_static... +lazy_static! { + pub static ref IDM_ALL_PERSONS: BuiltinGroup = BuiltinGroup { + name: "idm_all_persons", + description: "Builtin IDM dynamic group containing all persons.", + uuid: UUID_IDM_ALL_PERSONS, + members: Vec::with_capacity(0), + dyngroup: true, + dyngroup_filter: Some( + Filter::And(vec![ + Filter::Eq(Attribute::Class.to_string(), EntryClass::Person.to_string()), + Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()), + ]) + ), + extra_attributes: vec![ + // Enable account policy by default + (Attribute::Class, EntryClass::AccountPolicy.to_value()), + // Enforce this is a system protected object + (Attribute::Class, EntryClass::System.to_value()), + // MFA By Default + (Attribute::CredentialTypeMinimum, CredentialType::Mfa.into()), + ], + ..Default::default() + }; + + pub static ref IDM_ALL_ACCOUNTS: BuiltinGroup = BuiltinGroup { + name: "idm_all_accounts", + description: "Builtin IDM dynamic group containing all entries that can authenticate.", + uuid: UUID_IDM_ALL_ACCOUNTS, + members: Vec::with_capacity(0), + dyngroup: true, + dyngroup_filter: Some( + Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()), + ), + extra_attributes: vec![ + // Enable account policy by default + (Attribute::Class, EntryClass::AccountPolicy.to_value()), + // Enforce this is a system protected object + (Attribute::Class, EntryClass::System.to_value()), + ], + ..Default::default() + }; + + + pub static ref IDM_UI_ENABLE_EXPERIMENTAL_FEATURES: BuiltinGroup = BuiltinGroup { + name: "idm_ui_enable_experimental_features", + description: "Members of this group will have access to experimental web UI features.", + uuid: UUID_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES, + entry_managed_by: Some(UUID_IDM_ADMINS), + extra_attributes: vec![ + (Attribute::GrantUiHint, Value::UiHint(UiHint::ExperimentalFeatures)) + ], + ..Default::default() + }; + + /// Members of this group will have access to read the mail attribute of all persons and service accounts. + pub static ref IDM_ACCOUNT_MAIL_READ: BuiltinGroup = BuiltinGroup { + name: "idm_account_mail_read", + description: "Members of this group will have access to read the mail attribute of all persons and service accounts.", + entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS), + uuid: UUID_IDM_ACCOUNT_MAIL_READ, + ..Default::default() + }; + + /// This must be the last group to init to include the UUID of the other high priv groups. + pub static ref IDM_HIGH_PRIVILEGE_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_high_privilege", + uuid: UUID_IDM_HIGH_PRIVILEGE, + entry_managed_by: Some(UUID_IDM_ACCESS_CONTROL_ADMINS), + description: "Builtin IDM provided groups with high levels of access that should be audited and limited in modification.", + members: vec![ + UUID_SYSTEM_ADMINS, + UUID_IDM_ADMINS, + UUID_DOMAIN_ADMINS, + UUID_IDM_SERVICE_DESK, + UUID_IDM_RECYCLE_BIN_ADMINS, + UUID_IDM_SCHEMA_ADMINS, + UUID_IDM_ACCESS_CONTROL_ADMINS, + UUID_IDM_OAUTH2_ADMINS, + UUID_IDM_RADIUS_ADMINS, + UUID_IDM_ACCOUNT_POLICY_ADMINS, + UUID_IDM_RADIUS_SERVERS, + UUID_IDM_GROUP_ADMINS, + UUID_IDM_UNIX_ADMINS, + UUID_IDM_PEOPLE_PII_READ, + UUID_IDM_PEOPLE_ADMINS, + UUID_IDM_PEOPLE_ON_BOARDING, + UUID_IDM_SERVICE_ACCOUNT_ADMINS, + UUID_IDM_CLIENT_CERTIFICATE_ADMINS, + UUID_IDM_APPLICATION_ADMINS, + UUID_IDM_MAIL_ADMINS, + UUID_IDM_HIGH_PRIVILEGE, + ], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_APPLICATION_ADMINS_DL8: BuiltinGroup = BuiltinGroup { + name: "idm_application_admins", + uuid: UUID_IDM_APPLICATION_ADMINS, + description: "Builtin Application Administration Group.", + entry_managed_by: Some(UUID_IDM_ADMINS), + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; +} diff --git a/server/lib/src/migration_data/dl9/key_providers.rs b/server/lib/src/migration_data/dl9/key_providers.rs new file mode 100644 index 000000000..f6cd2b3cf --- /dev/null +++ b/server/lib/src/migration_data/dl9/key_providers.rs @@ -0,0 +1,18 @@ +use crate::constants::entries::{Attribute, EntryClass}; +use crate::constants::uuids::UUID_KEY_PROVIDER_INTERNAL; +use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew}; +use crate::value::Value; + +lazy_static! { + pub static ref E_KEY_PROVIDER_INTERNAL_DL6: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::KeyProvider.to_value()), + (Attribute::Class, EntryClass::KeyProviderInternal.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_KEY_PROVIDER_INTERNAL)), + (Attribute::Name, Value::new_iname("key_provider_internal")), + ( + Attribute::Description, + Value::new_utf8s("The default database internal cryptographic key provider.") + ) + ); +} diff --git a/server/lib/src/migration_data/dl9/mod.rs b/server/lib/src/migration_data/dl9/mod.rs new file mode 100644 index 000000000..78154d8b2 --- /dev/null +++ b/server/lib/src/migration_data/dl9/mod.rs @@ -0,0 +1,264 @@ +mod access; +mod accounts; +mod groups; +mod key_providers; +mod schema; +mod system_config; + +use self::access::*; +use self::accounts::*; +use self::groups::*; +use self::key_providers::*; +use self::schema::*; +use self::system_config::*; + +use crate::prelude::EntryInitNew; +use kanidm_proto::internal::OperationError; + +pub fn phase_1_schema_attrs() -> Vec { + vec![ + SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(), + SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(), + SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(), + SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(), + SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(), + SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(), + SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(), + SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(), + SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(), + SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(), + SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(), + SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(), + SCHEMA_ATTR_DOMAIN_NAME.clone().into(), + SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(), + SCHEMA_ATTR_DOMAIN_SSID.clone().into(), + SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(), + SCHEMA_ATTR_DOMAIN_UUID.clone().into(), + SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(), + SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(), + SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(), + SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(), + SCHEMA_ATTR_GIDNUMBER.clone().into(), + SCHEMA_ATTR_GRANT_UI_HINT.clone().into(), + SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(), + SCHEMA_ATTR_LOGINSHELL.clone().into(), + SCHEMA_ATTR_NAME_HISTORY.clone().into(), + SCHEMA_ATTR_NSUNIQUEID.clone().into(), + SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE + .clone() + .into(), + SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(), + SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(), + SCHEMA_ATTR_OAUTH2_SESSION.clone().into(), + SCHEMA_ATTR_PASSKEYS.clone().into(), + SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(), + SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(), + SCHEMA_ATTR_RADIUS_SECRET.clone().into(), + SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(), + SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(), + SCHEMA_ATTR_SYNC_COOKIE.clone().into(), + SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_UNIX_PASSWORD.clone().into(), + SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(), + SCHEMA_ATTR_DENIED_NAME.clone().into(), + SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(), + SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(), + // DL4 + SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(), + SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4 + .clone() + .into(), + // DL5 + // DL6 + SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(), + SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(), + SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(), + SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(), + SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(), + // DL7 + SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(), + SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(), + SCHEMA_ATTR_REFERS_DL7.clone().into(), + SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(), + SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(), + SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(), + SCHEMA_ATTR_MAIL_DL7.clone().into(), + SCHEMA_ATTR_LEGALNAME_DL7.clone().into(), + SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(), + // DL8 + SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(), + SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(), + SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(), + // DL9 + SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(), + SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(), + ] +} + +pub fn phase_2_schema_classes() -> Vec { + vec![ + SCHEMA_CLASS_DYNGROUP.clone().into(), + SCHEMA_CLASS_ORGPERSON.clone().into(), + SCHEMA_CLASS_POSIXACCOUNT.clone().into(), + SCHEMA_CLASS_POSIXGROUP.clone().into(), + SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(), + // DL4 + SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(), + // DL5 + SCHEMA_CLASS_ACCOUNT_DL5.clone().into(), + SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(), + // DL6 + SCHEMA_CLASS_GROUP_DL6.clone().into(), + SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(), + SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(), + SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(), + // DL7 + SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(), + SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(), + SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(), + // DL8 + SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(), + SCHEMA_CLASS_APPLICATION_DL8.clone().into(), + SCHEMA_CLASS_PERSON_DL8.clone().into(), + // DL9 + SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(), + SCHEMA_CLASS_DOMAIN_INFO_DL9.clone().into(), + ] +} + +pub fn phase_3_key_provider() -> Vec { + vec![E_KEY_PROVIDER_INTERNAL_DL6.clone()] +} + +pub fn phase_4_system_entries() -> Vec { + vec![ + E_SYSTEM_INFO_V1.clone(), + E_DOMAIN_INFO_DL6.clone(), + E_SYSTEM_CONFIG_V1.clone(), + ] +} + +pub fn phase_5_builtin_admin_entries() -> Result, OperationError> { + Ok(vec![ + BUILTIN_ACCOUNT_ADMIN.clone().into(), + BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(), + BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?, + BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?, + // We need to push anonymous *after* groups due to entry-managed-by + BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(), + ]) +} + +pub fn phase_6_builtin_non_admin_entries() -> Result, OperationError> { + Ok(vec![ + BUILTIN_GROUP_DOMAIN_ADMINS.clone().try_into()?, + BUILTIN_GROUP_SCHEMA_ADMINS.clone().try_into()?, + BUILTIN_GROUP_ACCESS_CONTROL_ADMINS.clone().try_into()?, + BUILTIN_GROUP_UNIX_ADMINS.clone().try_into()?, + BUILTIN_GROUP_RECYCLE_BIN_ADMINS.clone().try_into()?, + BUILTIN_GROUP_SERVICE_DESK.clone().try_into()?, + BUILTIN_GROUP_OAUTH2_ADMINS.clone().try_into()?, + BUILTIN_GROUP_RADIUS_SERVICE_ADMINS.clone().try_into()?, + BUILTIN_GROUP_ACCOUNT_POLICY_ADMINS.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_ADMINS.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_PII_READ.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_ON_BOARDING.clone().try_into()?, + BUILTIN_GROUP_SERVICE_ACCOUNT_ADMINS.clone().try_into()?, + BUILTIN_GROUP_MAIL_SERVICE_ADMINS_DL8.clone().try_into()?, + IDM_GROUP_ADMINS_V1.clone().try_into()?, + IDM_ALL_PERSONS.clone().try_into()?, + IDM_ALL_ACCOUNTS.clone().try_into()?, + BUILTIN_IDM_RADIUS_SERVERS_V1.clone().try_into()?, + BUILTIN_IDM_MAIL_SERVERS_DL8.clone().try_into()?, + BUILTIN_GROUP_PEOPLE_SELF_NAME_WRITE_DL7 + .clone() + .try_into()?, + IDM_PEOPLE_SELF_MAIL_WRITE_DL7.clone().try_into()?, + BUILTIN_GROUP_CLIENT_CERTIFICATE_ADMINS_DL7 + .clone() + .try_into()?, + BUILTIN_GROUP_APPLICATION_ADMINS_DL8.clone().try_into()?, + // Write deps on read.clone().try_into()?, so write must be added first. + // All members must exist before we write HP + IDM_HIGH_PRIVILEGE_DL8.clone().try_into()?, + // other things + IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone().try_into()?, + IDM_ACCOUNT_MAIL_READ.clone().try_into()?, + ]) +} + +pub fn phase_7_builtin_access_control_profiles() -> Vec { + vec![ + // Built in access controls. + IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(), + IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(), + IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(), + IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(), + IDM_ACP_ACP_MANAGE_V1.clone().into(), + IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(), + IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(), + IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(), + IDM_ACP_RADIUS_SERVERS_V1.clone().into(), + IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(), + IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(), + IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(), + IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1 + .clone() + .into(), + IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(), + IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(), + IDM_ACP_GROUP_READ_V1.clone().into(), + IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(), + IDM_ACP_PEOPLE_PII_READ_V1.clone().into(), + IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_READ_V1.clone().into(), + IDM_ACP_PEOPLE_MANAGE_V1.clone().into(), + IDM_ACP_PEOPLE_DELETE_V1.clone().into(), + IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), + IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(), + IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 + .clone() + .into(), + IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 + .clone() + .into(), + IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(), + // DL4 + // DL5 + // DL6 + IDM_ACP_PEOPLE_CREATE_DL6.clone().into(), + IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(), + // DL7 + IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(), + IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(), + // DL8 + IDM_ACP_SELF_READ_DL8.clone().into(), + IDM_ACP_SELF_WRITE_DL8.clone().into(), + IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(), + IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(), + IDM_ACP_MAIL_SERVERS_DL8.clone().into(), + IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(), + // DL9 + IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(), + IDM_ACP_GROUP_MANAGE_DL9.clone().into(), + IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(), + ] +} diff --git a/server/lib/src/migration_data/dl9/schema.rs b/server/lib/src/migration_data/dl9/schema.rs new file mode 100644 index 000000000..1a3ebbca9 --- /dev/null +++ b/server/lib/src/migration_data/dl9/schema.rs @@ -0,0 +1,1506 @@ +//! Schema Entries +use crate::constants::entries::{Attribute, EntryClass}; +use crate::constants::uuids::*; +use crate::schema::{SchemaAttribute, SchemaClass}; +use crate::value::IndexType; +use crate::value::SyntaxType; + +lazy_static!( + +pub static ref SCHEMA_ATTR_DISPLAYNAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DISPLAYNAME, + name: Attribute::DisplayName, + description: "The publicly visible display name of this person".to_string(), + + index: vec![IndexType::Equality], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DISPLAYNAME_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DISPLAYNAME, + name: Attribute::DisplayName, + description: "The publicly visible display name of this person".to_string(), + + index: vec![IndexType::Equality, IndexType::SubString], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_MAIL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_MAIL, + name: Attribute::Mail, + description: "Mail addresses of the object".to_string(), + + index: vec![IndexType::Equality], + unique: true, + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::EmailAddress, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_MAIL_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_MAIL, + name: Attribute::Mail, + description: "Mail addresses of the object".to_string(), + + index: vec![IndexType::Equality, IndexType::SubString], + unique: true, + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::EmailAddress, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_EC_KEY_PRIVATE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_EC_KEY_PRIVATE, + name: Attribute::IdVerificationEcKey, + description: "Account verification private key".to_string(), + + index: vec![IndexType::Presence], + unique: false, + sync_allowed: false, + syntax: SyntaxType::EcKeyPrivate, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SSH_PUBLICKEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SSH_PUBLICKEY, + name: Attribute::SshPublicKey, + description: "SSH public keys of the object".to_string(), + + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::SshKey, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_PRIMARY_CREDENTIAL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PRIMARY_CREDENTIAL, + name: Attribute::PrimaryCredential, + description: "Primary credential material of the account for authentication interactively".to_string(), + + index: vec![IndexType::Presence], + sync_allowed: true, + syntax: SyntaxType::Credential, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LEGALNAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LEGALNAME, + name: Attribute::LegalName, + description: "The private and sensitive legal name of this person".to_string(), + + index: vec![IndexType::Equality], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LEGALNAME_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LEGALNAME, + name: Attribute::LegalName, + description: "The private and sensitive legal name of this person".to_string(), + + index: vec![IndexType::Equality, IndexType::SubString], + sync_allowed: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_NAME_HISTORY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_NAME_HISTORY, + name: Attribute::NameHistory, + description: "The history of names that a person has had".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::AuditLogString, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_RADIUS_SECRET: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_RADIUS_SECRET, + name: Attribute::RadiusSecret, + description: "The accounts generated radius secret for device network authentication".to_string(), + + sync_allowed: true, + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_NAME, + name: Attribute::DomainName, + description: "The domain's DNS name for webauthn and SPN generation purposes".to_string(), + + index: vec![IndexType::Equality, IndexType::Presence], + unique: true, + syntax: SyntaxType::Utf8StringIname, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND, + name: Attribute::LdapAllowUnixPwBind, + description: "Configuration to enable binds to LDAP objects using their UNIX password".to_string(), + + unique: false, + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_LDAP_BASEDN: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_LDAP_BASEDN, + name: Attribute::DomainLdapBasedn, + description: "The domain's optional ldap basedn. If unset defaults to domain components of domain name".to_string(), + + unique: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_DISPLAY_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_DISPLAY_NAME, + name: Attribute::DomainDisplayName, + description: "The user-facing display name of the Kanidm domain".to_string(), + + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_UUID: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_UUID, + name: Attribute::DomainUuid, + description: "The domain's uuid, used in CSN and trust relationships".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::Uuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_SSID: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_SSID, + name: Attribute::DomainSsid, + description: "The domains site-wide SSID for device autoconfiguration of wireless".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::Utf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DENIED_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DENIED_NAME, + name: Attribute::DeniedName, + description: "Iname values that are not allowed to be used in 'name'.".to_string(), + + syntax: SyntaxType::Utf8StringIname, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DENIED_NAME_DL10: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DENIED_NAME, + name: Attribute::DeniedName, + description: "Iname values that are not allowed to be used in 'name'.".to_string(), + + syntax: SyntaxType::Utf8StringIname, + multivalue: true, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_TOKEN_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_TOKEN_KEY, + name: Attribute::DomainTokenKey, + description: "The domain token encryption private key (NOT USED)".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR, + name: Attribute::FernetPrivateKeyStr, + description: "The token encryption private key".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_GIDNUMBER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_GIDNUMBER, + name: Attribute::GidNumber, + description: "The groupid (uid) number of a group or account.to_string(). This is the same value as the UID number on posix accounts for security reasons".to_string(), + + index: vec![IndexType::Equality], + unique: true, + sync_allowed: true, + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_BADLIST_PASSWORD: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_BADLIST_PASSWORD, + name: Attribute::BadlistPassword, + description: "A password that is badlisted meaning that it can not be set as a valid password by any user account".to_string(), + + multivalue: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_AUTH_SESSION_EXPIRY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_AUTH_SESSION_EXPIRY, + name: Attribute::AuthSessionExpiry, + description: "An expiration time for an authentication session".to_string(), + + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY, + name: Attribute::PrivilegeExpiry, + description: "An expiration time for a privileged authentication session".to_string(), + + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH, + name: Attribute::AuthPasswordMinimumLength, + description: "Minimum length of passwords".to_string(), + + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LOGINSHELL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LOGINSHELL, + name: Attribute::LoginShell, + description: "A POSIX user's UNIX login shell".to_string(), + + sync_allowed: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_UNIX_PASSWORD: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_UNIX_PASSWORD, + name: Attribute::UnixPassword, + description: "A POSIX user's UNIX login password".to_string(), + + index: vec![IndexType::Presence], + syntax: SyntaxType::Credential, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_NSUNIQUEID: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_NSUNIQUEID, + name: Attribute::NsUniqueId, + description: "A unique id compatibility for 389-ds/dsee".to_string(), + + index: vec![IndexType::Equality], + unique: true, + sync_allowed: true, + syntax: SyntaxType::NsUniqueId, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ACCOUNT_EXPIRE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ACCOUNT_EXPIRE, + name: Attribute::AccountExpire, + description: "The datetime after which this account no longer may authenticate".to_string(), + + sync_allowed: true, + syntax: SyntaxType::DateTime, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ACCOUNT_VALID_FROM: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ACCOUNT_VALID_FROM, + name: Attribute::AccountValidFrom, + description: "The datetime after which this account may commence authenticating".to_string(), + + sync_allowed: true, + syntax: SyntaxType::DateTime, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST, + name: Attribute::WebauthnAttestationCaList, + description: "A set of CA's that limit devices that can be used with webauthn".to_string(), + + syntax: SyntaxType::WebauthnAttestationCaList, + multivalue: true, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_NAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_NAME, + name: Attribute::OAuth2RsName, + description: "The unique name of an external Oauth2 resource".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::Utf8StringIname, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_ORIGIN: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_ORIGIN, + name: Attribute::OAuth2RsOrigin, + description: "The origin domain of an oauth2 resource server".to_string(), + + syntax: SyntaxType::Url, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_ORIGIN, + name: Attribute::OAuth2RsOrigin, + description: "The origin domain of an OAuth2 client".to_string(), + + syntax: SyntaxType::Url, + multivalue: true, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING, + name: Attribute::OAuth2RsOriginLanding, + description: "The landing page of an RS, that will automatically trigger the auth process".to_string(), + + syntax: SyntaxType::Url, + ..Default::default() +}; + +// Introduced in DomainLevel4 +pub static ref SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT, + name: Attribute::OAuth2AllowLocalhostRedirect, + description: "Allow public clients associated to this RS to redirect to localhost".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP, + name: Attribute::OAuth2RsClaimMap, + description: "A set of custom claims mapped to group memberships of accounts".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + // CHANGE ME + syntax: SyntaxType::OauthClaimMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP, + name: Attribute::OAuth2RsScopeMap, + description: "A reference to a group mapped to scopes for the associated oauth2 resource server".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::OauthScopeMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP, + name: Attribute::OAuth2RsSupScopeMap, + description: "A reference to a group mapped to scopes for the associated oauth2 resource server".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::OauthScopeMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET, + name: Attribute::OAuth2RsBasicSecret, + description: "When using oauth2 basic authentication, the secret string of the resource server".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY, + name: Attribute::OAuth2RsTokenKey, + description: "An oauth2 resource servers unique token signing key".to_string(), + + syntax: SyntaxType::SecretUtf8String, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES, + name: Attribute::OAuth2RsImplicitScopes, + description: "An oauth2 resource servers scopes that are implicitly granted to all users".to_string(), + + multivalue: true, + syntax: SyntaxType::OauthScope, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP, + name: Attribute::OAuth2ConsentScopeMap, + description: "A set of scopes mapped from a relying server to a user, where the user has previously consented to the following. If changed or deleted, consent will be re-sought".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::OauthScopeMap, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI, + name: Attribute::OAuth2StrictRedirectUri, + description: "Represents if strict redirect uri enforcement is enabled.".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + + +pub static ref SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE, + name: Attribute::OAuth2DeviceFlowEnable, + description: "Represents if OAuth2 Device Flow is permitted on this client.".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ES256_PRIVATE_KEY_DER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ES256_PRIVATE_KEY_DER, + name: Attribute::Es256PrivateKeyDer, + description: "An es256 private key".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_RS256_PRIVATE_KEY_DER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_RS256_PRIVATE_KEY_DER, + name: Attribute::Rs256PrivateKeyDer, + description: "An rs256 private key".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY, + name: Attribute::JwsEs256PrivateKey, + description: "An es256 private key for jws".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::JwsKeyEs256, + ..Default::default() +}; + +// TO BE REMOVED IN A FUTURE RELEASE +pub static ref SCHEMA_ATTR_PRIVATE_COOKIE_KEY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PRIVATE_COOKIE_KEY, + name: Attribute::PrivateCookieKey, + description: "An private cookie hmac key".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE, + name: Attribute::OAuth2AllowInsecureClientDisablePkce, + description: "Allows disabling of PKCE for insecure OAuth2 clients".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE, + name: Attribute::OAuth2JwtLegacyCryptoEnable, + description: "Allows enabling legacy JWT cryptograhpy for clients".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN, + name: Attribute::CredentialUpdateIntentToken, + description: "The status of a credential update intent token".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::IntentToken, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_PASSKEYS: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PASSKEYS, + name: Attribute::PassKeys, + description: "A set of registered passkeys".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::Passkey, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ATTESTED_PASSKEYS: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ATTESTED_PASSKEYS, + name: Attribute::AttestedPasskeys, + description: "A set of registered device keys".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + sync_allowed: true, + syntax: SyntaxType::AttestedPasskey, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DYNGROUP_FILTER: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DYNGROUP_FILTER, + name: Attribute::DynGroupFilter, + description: "A filter describing the set of entries to add to a dynamic group".to_string(), + + syntax: SyntaxType::JsonFilter, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME, + name: Attribute::OAuth2PreferShortUsername, + description: "Use 'name' instead of 'spn' in the preferred_username claim".to_string(), + + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_API_TOKEN_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_API_TOKEN_SESSION, + name: Attribute::ApiTokenSession, + description: "A session entry related to an issued API token".to_string(), + + index: vec![IndexType::Equality], + unique: true, + multivalue: true, + syntax: SyntaxType::ApiToken, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION, + name: Attribute::UserAuthTokenSession, + description: "A session entry related to an issued user auth token".to_string(), + + index: vec![IndexType::Equality], + unique: true, + multivalue: true, + syntax: SyntaxType::Session, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_OAUTH2_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_OAUTH2_SESSION, + name: Attribute::OAuth2Session, + description: "A session entry to an active oauth2 session, bound to a parent user auth token".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::Oauth2Session, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_TOKEN_SESSION: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_TOKEN_SESSION, + name: Attribute::SyncTokenSession, + description: "A session entry related to an issued sync token".to_string(), + + index: vec![IndexType::Equality], + unique: true, + syntax: SyntaxType::ApiToken, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_COOKIE: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_COOKIE, + name: Attribute::SyncCookie, + description: "A private sync cookie for a remote IDM source".to_string(), + + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_GRANT_UI_HINT: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_GRANT_UI_HINT, + name: Attribute::GrantUiHint, + description: "A UI hint that is granted via membership to a group".to_string(), + + index: vec![IndexType::Equality], + multivalue: true, + syntax: SyntaxType::UiHint, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL, + name: Attribute::SyncCredentialPortal, + description: "The url of an external credential portal for synced accounts to visit to update their credentials".to_string(), + + syntax: SyntaxType::Url, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_SYNC_YIELD_AUTHORITY: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_SYNC_YIELD_AUTHORITY, + name: Attribute::SyncYieldAuthority, + description: "A set of attributes that have their authority yielded to Kanidm in a sync agreement".to_string(), + + multivalue: true, + syntax: SyntaxType::Utf8StringInsensitive, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM, + name: Attribute::CredentialTypeMinimum, + description: "The minimum level of credential type that can satisfy this policy".to_string(), + + multivalue: false, + syntax: SyntaxType::CredentialType, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS, + name: Attribute::LimitSearchMaxResults, + description: "The maximum number of query results that may be returned in a single operation".to_string(), + + multivalue: false, + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST, + name: Attribute::LimitSearchMaxFilterTest, + description: "The maximum number of entries that may be examined in a partially indexed query".to_string(), + + multivalue: false, + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_INTERNAL_DATA, + name: Attribute::KeyInternalData, + description: "".to_string(), + multivalue: true, + syntax: SyntaxType::KeyInternal, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_PROVIDER_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_PROVIDER, + name: Attribute::KeyProvider, + description: "".to_string(), + multivalue: false, + syntax: SyntaxType::ReferenceUuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_ACTION_ROTATE, + name: Attribute::KeyActionRotate, + description: "".to_string(), + multivalue: false, + // Ephemeral action. + phantom: true, + syntax: SyntaxType::DateTime, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_ACTION_REVOKE, + name: Attribute::KeyActionRevoke, + description: "".to_string(), + multivalue: true, + // Ephemeral action. + phantom: true, + syntax: SyntaxType::HexString, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256, + name: Attribute::KeyActionImportJwsEs256, + description: "".to_string(), + multivalue: true, + // Ephemeral action. + phantom: true, + syntax: SyntaxType::PrivateBinary, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_PATCH_LEVEL_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_PATCH_LEVEL, + name: Attribute::PatchLevel, + description: "".to_string(), + syntax: SyntaxType::Uint32, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT, + name: Attribute::DomainDevelopmentTaint, + description: "A flag to show that the domain has been run on a development build, and will need additional work to upgrade/migrate.".to_string(), + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS, + name: Attribute::DomainAllowEasterEggs, + description: "A flag to enable easter eggs in the server that may not always be wanted by all users/deployments.".to_string(), + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_REFERS_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_REFERS, + name: Attribute::Refers, + description: "A reference to linked object".to_string(), + multivalue: false, + syntax: SyntaxType::ReferenceUuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_LINKED_GROUP_DL8: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_LINKED_GROUP, + name: Attribute::LinkedGroup, + description: "A reference linking a group to an entry".to_string(), + + multivalue: false, + syntax: SyntaxType::ReferenceUuid, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK, + name: Attribute::AllowPrimaryCredFallback, + description: "Allow fallback to primary password if no POSIX password exists".to_string(), + + multivalue: false, + syntax: SyntaxType::Boolean, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_CERTIFICATE_DL7: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_CERTIFICATE, + name: Attribute::Certificate, + description: "An x509 Certificate".to_string(), + multivalue: false, + syntax: SyntaxType::Certificate, + ..Default::default() +}; + +pub static ref SCHEMA_ATTR_APPLICATION_PASSWORD_DL8: SchemaAttribute = SchemaAttribute { + uuid: UUID_SCHEMA_ATTR_APPLICATION_PASSWORD, + name: Attribute::ApplicationPassword, + description: "A set of application passwords".to_string(), + + multivalue: true, + syntax: SyntaxType::ApplicationPassword, + ..Default::default() +}; + +// === classes === + +pub static ref SCHEMA_CLASS_PERSON: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_PERSON, + name: EntryClass::Person.into(), + description: "Object representation of a person".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::Mail, + Attribute::LegalName, + ], + systemmust: vec![ + Attribute::DisplayName, + Attribute::Name, + Attribute::IdVerificationEcKey], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_PERSON_DL5: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_PERSON, + name: EntryClass::Person.into(), + description: "Object representation of a person".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::CredentialUpdateIntentToken, + Attribute::SshPublicKey, + Attribute::RadiusSecret, + Attribute::OAuth2ConsentScopeMap, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::Mail, + Attribute::LegalName, + ], + systemmust: vec![ + Attribute::IdVerificationEcKey + ], + systemexcludes: vec![EntryClass::ServiceAccount.into(), EntryClass::Application.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_PERSON_DL8: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_PERSON, + name: EntryClass::Person.into(), + description: "Object representation of a person".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::CredentialUpdateIntentToken, + Attribute::SshPublicKey, + Attribute::RadiusSecret, + Attribute::OAuth2ConsentScopeMap, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::Mail, + Attribute::LegalName, + Attribute::ApplicationPassword, + ], + systemmust: vec![ + Attribute::IdVerificationEcKey + ], + systemexcludes: vec![EntryClass::ServiceAccount.into(), EntryClass::Application.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ORGPERSON: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_ORGPERSON, + name: EntryClass::OrgPerson.into(), + description: "Object representation of an org person".to_string(), + + systemmay: vec![ + Attribute::LegalName + ], + systemmust: vec![ + Attribute::Mail, + Attribute::DisplayName, + Attribute::Name + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_GROUP_DL6: 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, + Attribute::GrantUiHint, + Attribute::Description, + Attribute::Mail, + ], + systemmust: vec![ + Attribute::Name, + Attribute::Spn], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DYNGROUP: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DYNGROUP, + name: EntryClass::DynGroup.into(), + description: "Object representation of a dynamic group".to_string(), + + systemmust: vec![Attribute::DynGroupFilter], + systemmay: vec![Attribute::DynMember], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT_POLICY_DL6: 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, + Attribute::PrivilegeExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + ], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT_POLICY_DL8: 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, + Attribute::PrivilegeExpiry, + Attribute::AuthPasswordMinimumLength, + Attribute::CredentialTypeMinimum, + Attribute::WebauthnAttestationCaList, + Attribute::LimitSearchMaxResults, + Attribute::LimitSearchMaxFilterTest, + Attribute::AllowPrimaryCredFallback, + ], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_ACCOUNT, + name: EntryClass::Account.into(), + description: "Object representation of an account".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::PrimaryCredential, + Attribute::PassKeys, + Attribute::AttestedPasskeys, + Attribute::CredentialUpdateIntentToken, + Attribute::SshPublicKey, + Attribute::RadiusSecret, + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::Mail, + Attribute::OAuth2ConsentScopeMap, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::Description, + Attribute::NameHistory, + ], + systemmust: vec![ + Attribute::DisplayName, + Attribute::Name, + Attribute::Spn + ], + systemsupplements: vec![ + EntryClass::Person.into(), + EntryClass::ServiceAccount.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_ACCOUNT_DL5: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_ACCOUNT, + name: EntryClass::Account.into(), + description: "Object representation of an account".to_string(), + + sync_allowed: true, + systemmay: vec![ + Attribute::AccountExpire, + Attribute::AccountValidFrom, + Attribute::NameHistory, + ], + systemmust: vec![ + Attribute::DisplayName, + Attribute::Name, + Attribute::Spn + ], + systemsupplements: vec![ + EntryClass::Person.into(), + EntryClass::ServiceAccount.into(), + EntryClass::OAuth2ResourceServer.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL6: 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, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::OAuth2ConsentScopeMap, + Attribute::Description, + + Attribute::Mail, + Attribute::PrimaryCredential, + Attribute::ApiTokenSession, + + Attribute::JwsEs256PrivateKey, + ], + systemexcludes: vec![EntryClass::Person.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SERVICE_ACCOUNT_DL7: 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, + Attribute::UserAuthTokenSession, + Attribute::OAuth2Session, + Attribute::OAuth2ConsentScopeMap, + Attribute::Description, + + Attribute::Mail, + Attribute::PrimaryCredential, + Attribute::ApiTokenSession, + ], + systemexcludes: vec![EntryClass::Person.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT, + name: EntryClass::SyncAccount.into(), + description: "Object representation of sync account".to_string(), + + systemmust: vec![Attribute::Name], + systemmay: vec![ + Attribute::SyncTokenSession, + Attribute::SyncCookie, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + Attribute::JwsEs256PrivateKey, + ], + systemexcludes: vec![EntryClass::Account.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SYNC_ACCOUNT_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_SYNC_ACCOUNT, + name: EntryClass::SyncAccount.into(), + description: "Object representation of sync account".to_string(), + + systemmust: vec![Attribute::Name], + systemmay: vec![ + Attribute::SyncTokenSession, + Attribute::SyncCookie, + Attribute::SyncCredentialPortal, + Attribute::SyncYieldAuthority, + ], + systemexcludes: vec![EntryClass::Account.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::PrivateCookieKey, + Attribute::FernetPrivateKeyStr, + Attribute::Es256PrivateKeyDer, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL8: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::Image, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL9: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::Image, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + Attribute::DomainAllowEasterEggs, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::DomainDisplayName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL10: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO, + name: EntryClass::DomainInfo.into(), + description: "Local domain information and configuration".to_string(), + + systemmay: vec![ + Attribute::DomainSsid, + Attribute::DomainLdapBasedn, + Attribute::LdapAllowUnixPwBind, + Attribute::Image, + Attribute::PatchLevel, + Attribute::DomainDevelopmentTaint, + Attribute::DomainAllowEasterEggs, + Attribute::DomainDisplayName, + ], + systemmust: vec![ + Attribute::Name, + Attribute::DomainUuid, + Attribute::DomainName, + Attribute::Version, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_POSIXGROUP: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_POSIXGROUP, + name: EntryClass::PosixGroup.into(), + description: "Object representation of a posix group, requires group".to_string(), + + sync_allowed: true, + systemmust: vec![Attribute::GidNumber], + systemsupplements: vec![Attribute::Group.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_POSIXACCOUNT: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_POSIXACCOUNT, + name: EntryClass::PosixAccount.into(), + description: "Object representation of a posix account, requires account".to_string(), + + sync_allowed: true, + systemmay: vec![Attribute::LoginShell, Attribute::UnixPassword], + systemmust: vec![Attribute::GidNumber], + systemsupplements: vec![Attribute::Account.into()], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_SYSTEM_CONFIG: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_SYSTEM_CONFIG, + name: EntryClass::SystemConfig.into(), + description: "The class representing a system (topologies) configuration options".to_string(), + + systemmay: vec![ + Attribute::Description, + Attribute::BadlistPassword, + Attribute::AuthSessionExpiry, + Attribute::PrivilegeExpiry, + Attribute::DeniedName + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL4: 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, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2RsOriginLanding, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + ], + systemmust: vec![ + Attribute::OAuth2RsName, + Attribute::DisplayName, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL5: 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, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::OAuth2RsOriginLanding, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + Attribute::OAuth2Session, + ], + systemmust: vec![ + Attribute::OAuth2RsOrigin, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS, + name: EntryClass::OAuth2ResourceServer.into(), + description: "The class representing a configured OAuth2 Client".to_string(), + + systemmay: vec![ + Attribute::Description, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2StrictRedirectUri, + ], + systemmust: vec![ + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_DL9: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS, + name: EntryClass::OAuth2ResourceServer.into(), + description: "The class representing a configured OAuth2 Client".to_string(), + + systemmay: vec![ + Attribute::Description, + Attribute::OAuth2RsScopeMap, + Attribute::OAuth2RsSupScopeMap, + Attribute::Rs256PrivateKeyDer, + Attribute::OAuth2JwtLegacyCryptoEnable, + Attribute::OAuth2PreferShortUsername, + Attribute::Image, + Attribute::OAuth2RsClaimMap, + Attribute::OAuth2Session, + Attribute::OAuth2RsOrigin, + Attribute::OAuth2StrictRedirectUri, + Attribute::OAuth2DeviceFlowEnable, + ], + systemmust: vec![ + Attribute::OAuth2RsOriginLanding, + Attribute::OAuth2RsTokenKey, + Attribute::Es256PrivateKeyDer, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC, + name: EntryClass::OAuth2ResourceServerBasic.into(), + description: "The class representing a configured OAuth2 client authenticated with HTTP basic authentication".to_string(), + + systemmay: vec![ + Attribute::OAuth2AllowInsecureClientDisablePkce, + ], + systemmust: vec![ Attribute::OAuth2RsBasicSecret], + systemexcludes: vec![ EntryClass::OAuth2ResourceServerPublic.into()], + ..Default::default() +}; + +// Introduced in DomainLevel4 +pub static ref SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_OAUTH2_RS_PUBLIC, + name: EntryClass::OAuth2ResourceServerPublic.into(), + description: "The class representing a configured Public OAuth2 Client with PKCE verification".to_string(), + + systemmay: vec![Attribute::OAuth2AllowLocalhostRedirect], + systemexcludes: vec![EntryClass::OAuth2ResourceServerBasic.into()], + ..Default::default() +}; + +// ========================================= +// KeyProviders + +pub static ref SCHEMA_CLASS_KEY_PROVIDER_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_PROVIDER, + name: EntryClass::KeyProvider.into(), + description: "A provider for cryptographic key storage and operations".to_string(), + systemmay: vec![ + Attribute::Description, + ], + systemmust: vec![ + Attribute::Name, + ], + systemsupplements: vec![ + EntryClass::KeyProviderInternal.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_PROVIDER_INTERNAL, + name: EntryClass::KeyProviderInternal.into(), + description: "The Kanidm internal cryptographic key provider".to_string(), + ..Default::default() +}; + +// ========================================= +// KeyObjects + +pub static ref SCHEMA_CLASS_KEY_OBJECT_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT, + name: EntryClass::KeyObject.into(), + description: "A cryptographic key object that can be used by a provider".to_string(), + systemmust: vec![ + Attribute::KeyProvider, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT_JWT_ES256, + name: EntryClass::KeyObjectJwtEs256.into(), + description: "A marker class indicating that this keyobject must provide jwt es256 capability.".to_string(), + systemsupplements: vec![ + EntryClass::KeyObject.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM, + name: EntryClass::KeyObjectJweA128GCM.into(), + description: "A marker class indicating that this keyobject must provide jwe aes-256-gcm capability.".to_string(), + systemsupplements: vec![ + EntryClass::KeyObject.into(), + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_KEY_OBJECT_INTERNAL, + name: EntryClass::KeyObjectInternal.into(), + description: "A cryptographic key object that can be used by the internal provider".to_string(), + systemmay: vec![ + Attribute::KeyInternalData, + ], + systemsupplements: vec![ + EntryClass::KeyObject.into(), + ], + ..Default::default() +}; + +// ========================================= + +pub static ref SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_CLIENT_CERTIFICATE, + name: EntryClass::ClientCertificate.into(), + description: "A client authentication certificate".to_string(), + systemmay: vec![], + systemmust: vec![ + Attribute::Certificate, + Attribute::Refers, + ], + ..Default::default() +}; + +pub static ref SCHEMA_CLASS_APPLICATION_DL8: SchemaClass = SchemaClass { + uuid: UUID_SCHEMA_CLASS_APPLICATION, + name: EntryClass::Application.into(), + + description: "The class representing an application".to_string(), + systemmust: vec![Attribute::Name, Attribute::LinkedGroup], + systemmay: vec![Attribute::Description], + systemsupplements: vec![EntryClass::ServiceAccount.into()], + ..Default::default() +}; + +); diff --git a/server/lib/src/migration_data/dl9/system_config.rs b/server/lib/src/migration_data/dl9/system_config.rs new file mode 100644 index 000000000..107bd8bbe --- /dev/null +++ b/server/lib/src/migration_data/dl9/system_config.rs @@ -0,0 +1,1073 @@ +use crate::constants::uuids::*; + +use crate::entry::{Entry, EntryInit, EntryInitNew, EntryNew}; +use crate::prelude::{Attribute, EntryClass}; +use crate::value::Value; + +// Default entries for system_config +// This is separated because the password badlist section may become very long + +lazy_static! { + pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::SystemInfo.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_SYSTEM_INFO)), + ( + Attribute::Description, + Value::new_utf8s("System (local) info and metadata object.") + ), + (Attribute::Version, Value::Uint32(20)) + ); + pub static ref E_DOMAIN_INFO_DL6: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::DomainInfo.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Class, EntryClass::KeyObject.to_value()), + (Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()), + (Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()), + (Attribute::Name, Value::new_iname("domain_local")), + (Attribute::Uuid, Value::Uuid(UUID_DOMAIN_INFO)), + ( + Attribute::Description, + Value::new_utf8s("This local domain's info and metadata object.") + ) + ); + pub static ref E_SYSTEM_CONFIG_V1: EntryInitNew = entry_init!( + (Attribute::Class, EntryClass::Object.to_value()), + (Attribute::Class, EntryClass::SystemConfig.to_value()), + (Attribute::Class, EntryClass::System.to_value()), + (Attribute::Uuid, Value::Uuid(UUID_SYSTEM_CONFIG)), + ( + Attribute::Description, + Value::new_utf8s("System (replicated) configuration options.") + ), + ( + Attribute::BadlistPassword, + Value::new_iutf8("bad@no3IBTyqHu$list") + ), + ( + Attribute::BadlistPassword, + Value::new_iutf8( + "demo_badlist_shohfie3aeci2oobur0aru9uushah6EiPi2woh4hohngoighaiRuepieN3ongoo1" + ) + ), + ( + Attribute::BadlistPassword, + Value::new_iutf8("100preteamare") + ), + (Attribute::BadlistPassword, Value::new_iutf8("14defebrero")), + (Attribute::BadlistPassword, Value::new_iutf8("1life1love")), + (Attribute::BadlistPassword, Value::new_iutf8("1life2live")), + (Attribute::BadlistPassword, Value::new_iutf8("1love1life")), + (Attribute::BadlistPassword, Value::new_iutf8("1love4life")), + (Attribute::BadlistPassword, Value::new_iutf8("212224236248")), + (Attribute::BadlistPassword, Value::new_iutf8("2813308004")), + ( + Attribute::BadlistPassword, + Value::new_iutf8("2fast2furious") + ), + (Attribute::BadlistPassword, Value::new_iutf8("2gether4ever")), + (Attribute::BadlistPassword, Value::new_iutf8("2pacshakur")), + ( + Attribute::BadlistPassword, + Value::new_iutf8("30secondstomars") + ), + (Attribute::BadlistPassword, Value::new_iutf8("3doorsdown")), + (Attribute::BadlistPassword, Value::new_iutf8("6cyclemind")), + ( + Attribute::BadlistPassword, + Value::new_iutf8("
, + pub name: &'static str, + pub uuid: Uuid, + pub description: &'static str, + pub displayname: &'static str, +} + +#[cfg(test)] +impl Default for BuiltinAccount { + fn default() -> Self { + BuiltinAccount { + account_type: AccountType::ServiceAccount, + entry_managed_by: None, + name: "", + uuid: Uuid::new_v4(), + description: "", + displayname: "", + } + } +} + +#[cfg(test)] +impl From for crate::idm::account::Account { + fn from(value: BuiltinAccount) -> Self { + Self { + name: value.name.to_string(), + uuid: value.uuid, + displayname: value.displayname.to_string(), + spn: format!("{}@example.com", value.name), + mail_primary: None, + mail: Vec::with_capacity(0), + ..Default::default() + } + } +} + +impl From for EntryInitNew { + fn from(value: BuiltinAccount) -> Self { + let mut entry = EntryInitNew::new(); + entry.add_ava(Attribute::Name, Value::new_iname(value.name)); + #[allow(clippy::panic)] + if value.uuid >= DYNAMIC_RANGE_MINIMUM_UUID { + panic!("Builtin ACP has invalid UUID! {:?}", value); + } + entry.add_ava(Attribute::Uuid, Value::Uuid(value.uuid)); + entry.add_ava(Attribute::Description, Value::new_utf8s(value.description)); + entry.add_ava(Attribute::DisplayName, Value::new_utf8s(value.displayname)); + + if let Some(entry_manager) = value.entry_managed_by { + entry.add_ava(Attribute::EntryManagedBy, Value::Refer(entry_manager)); + } + + entry.set_ava( + Attribute::Class, + vec![ + EntryClass::Account.to_value(), + EntryClass::MemberOf.to_value(), + EntryClass::Object.to_value(), + ], + ); + match value.account_type { + AccountType::Person => entry.add_ava(Attribute::Class, EntryClass::Person.to_value()), + AccountType::ServiceAccount => { + entry.add_ava(Attribute::Class, EntryClass::ServiceAccount.to_value()) + } + } + entry + } +} diff --git a/server/lib/src/server/access/mod.rs b/server/lib/src/server/access/mod.rs index 4847bfa37..956bcb512 100644 --- a/server/lib/src/server/access/mod.rs +++ b/server/lib/src/server/access/mod.rs @@ -1159,6 +1159,7 @@ mod tests { }, Access, AccessClass, AccessControls, AccessControlsTransaction, AccessEffectivePermission, }; + use crate::migration_data::BUILTIN_ACCOUNT_ANONYMOUS; use crate::prelude::*; use crate::valueset::ValueSetIname; @@ -2511,6 +2512,7 @@ mod tests { #[test] fn test_access_enforce_scope_delete() { + sketching::test_init(); let ev1 = E_TESTPERSON_1.clone().into_sealed_committed(); let r_set = vec![Arc::new(ev1)]; @@ -3052,7 +3054,7 @@ mod tests { test_acp_search_reduce!(&se_a, vec![], r_set.clone(), ex_a_reduced); // Check that anonymous is denied even though it's a member of the group. - let anon: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(); + let anon: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS.clone().into(); let mut anon = anon.into_invalid_new(); anon.set_ava_set(&Attribute::MemberOf, ValueSetRefer::new(UUID_TEST_GROUP_1)); @@ -3352,7 +3354,7 @@ mod tests { #[test] fn test_access_delete_protect_system_ranges() { - let ev1: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(); + let ev1: EntryInitNew = BUILTIN_ACCOUNT_ANONYMOUS.clone().into(); let ev1 = ev1.into_sealed_committed(); let r_set = vec![Arc::new(ev1)]; diff --git a/server/lib/src/server/migrations.rs b/server/lib/src/server/migrations.rs index a1535d483..b53afa579 100644 --- a/server/lib/src/server/migrations.rs +++ b/server/lib/src/server/migrations.rs @@ -1,5 +1,6 @@ use crate::prelude::*; +use crate::migration_data; use kanidm_proto::internal::{ DomainUpgradeCheckItem as ProtoDomainUpgradeCheckItem, DomainUpgradeCheckReport as ProtoDomainUpgradeCheckReport, @@ -48,17 +49,24 @@ impl QueryServer { debug!(?db_domain_version, "Before setting internal domain info"); if db_domain_version == 0 { - // No domain info was present, so neither was the rest of the IDM. We need to bootstrap - // the base-schema here. - write_txn.initialise_schema_idm()?; + // This is here to catch when we increase domain levels but didn't create the migration + // hooks. If this fails it probably means you need to add another migration hook + // in the above. + debug_assert!(domain_target_level <= DOMAIN_MAX_LEVEL); - write_txn.reload()?; - - // Since we just loaded in a ton of schema, lets reindex it to make - // sure that some base IDM operations are fast. Since this is still - // very early in the bootstrap process, and very few entries exist, - // reindexing is very fast here. - write_txn.reindex(false)?; + // No domain info was present, so neither was the rest of the IDM. Bring up the + // full IDM here. + match domain_target_level { + DOMAIN_LEVEL_8 => write_txn.migrate_domain_7_to_8()?, + DOMAIN_LEVEL_9 => write_txn.migrate_domain_8_to_9()?, + DOMAIN_LEVEL_10 => write_txn.migrate_domain_9_to_10()?, + DOMAIN_LEVEL_11 => write_txn.migrate_domain_10_to_11()?, + _ => { + error!("Invalid requested domain target level for server bootstrap"); + debug_assert!(false); + return Err(OperationError::MG0009InvalidTargetLevelForBootstrap); + } + } } else { // Domain info was present, so we need to reflect that in our server // domain structures. If we don't do this, the in memory domain level @@ -71,23 +79,11 @@ impl QueryServer { write_txn.force_domain_reload(); write_txn.reload()?; - } - // Indicate the schema is now ready, which allows dyngroups to work when they - // are created in the next phase of migrations. - write_txn.set_phase(ServerPhase::SchemaReady); + // Indicate the schema is now ready, which allows dyngroups to work when they + // are created in the next phase of migrations. + write_txn.set_phase(ServerPhase::SchemaReady); - // No domain info was present, so neither was the rest of the IDM. We need to bootstrap - // the base entries here. - if db_domain_version == 0 { - // Init idm will now set the system config version and minimum domain - // level if none was present - write_txn.initialise_domain_info()?; - - // In this path because we create the dyn groups they are immediately added to the - // dyngroup cache and begin to operate. - write_txn.initialise_idm()?; - } else { // #2756 - if we *aren't* creating the base IDM entries, then we // need to force dyn groups to reload since we're now at schema // ready. This is done indirectly by ... reloading the schema again. @@ -97,13 +93,13 @@ impl QueryServer { // itself or a change to schema reloading. Since we aren't changing the // dyngroup here, we have to go via the schema reload path. write_txn.force_schema_reload(); - }; - // Reload as init idm affects access controls. - write_txn.reload()?; + // Reload as init idm affects access controls. + write_txn.reload()?; - // Domain info is now ready and reloaded, we can proceed. - write_txn.set_phase(ServerPhase::DomainInfoReady); + // Domain info is now ready and reloaded, we can proceed. + write_txn.set_phase(ServerPhase::DomainInfoReady); + } // This is the start of domain info related migrations which we will need in future // to handle replication. Due to the access control rework, and the addition of "managed by" @@ -126,20 +122,18 @@ impl QueryServer { // If the database domain info is a lower version than our target level, we reload. if domain_info_version < domain_target_level { write_txn - .internal_modify_uuid( - UUID_DOMAIN_INFO, - &ModifyList::new_purge_and_set( - Attribute::Version, - Value::new_uint32(domain_target_level), - ), - ) + .internal_apply_domain_migration(domain_target_level) .map(|()| { warn!("Domain level has been raised to {}", domain_target_level); })?; - // Reload if anything in migrations requires it - this triggers the domain migrations - // which in turn can trigger schema reloads etc. - reload_required = true; + // which in turn can trigger schema reloads etc. If the server was just brought up + // then we don't need the extra reload since we are already at the correct + // version of the server, and this call to set the target level is just for persistance + // of the value. + if domain_info_version != 0 { + reload_required = true; + } } else if domain_development_taint { // This forces pre-release versions to re-migrate each start up. This solves // the domain-version-sprawl issue so that during a development cycle we can @@ -182,9 +176,6 @@ impl QueryServer { // we would have skipped the patch level fix which needs to have occurred *first*. if reload_required { write_txn.reload()?; - // We are not yet at the schema phase where reindexes will auto-trigger - // so if one was required, do it now. - write_txn.reindex(false)?; } // Now set the db/domain devel taint flag to match our current release status @@ -206,7 +197,8 @@ impl QueryServer { // We are ready to run write_txn.set_phase(ServerPhase::Running); - // Commit all changes, this also triggers the reload. + // Commit all changes, this also triggers the final reload, this should be a no-op + // since we already did all the needed loads above. write_txn.commit()?; debug!("Database version check and migrations success! ☀️ "); @@ -217,7 +209,6 @@ impl QueryServer { impl QueryServerWriteTransaction<'_> { /// Apply a domain migration `to_level`. Panics if `to_level` is not greater than the active /// level. - #[cfg(test)] pub(crate) fn internal_apply_domain_migration( &mut self, to_level: u32, @@ -230,6 +221,23 @@ impl QueryServerWriteTransaction<'_> { .and_then(|()| self.reload()) } + fn internal_migrate_or_create_batch( + &mut self, + msg: &str, + entries: Vec, + ) -> Result<(), OperationError> { + let r: Result<(), _> = entries + .into_iter() + .try_for_each(|entry| self.internal_migrate_or_create(entry)); + + if let Err(err) = r { + error!(?err, msg); + debug_assert!(false); + } + + Ok(()) + } + #[instrument(level = "debug", skip_all)] /// - If the thing exists: /// - Ensure the set of attributes match and are present @@ -240,7 +248,7 @@ impl QueryServerWriteTransaction<'_> { /// This will extra classes an attributes alone! /// /// NOTE: `gen_modlist*` IS schema aware and will handle multivalue correctly! - pub fn internal_migrate_or_create( + fn internal_migrate_or_create( &mut self, e: Entry, ) -> Result<(), OperationError> { @@ -251,7 +259,7 @@ impl QueryServerWriteTransaction<'_> { /// list of attributes, so that if an admin has modified those values then we don't /// stomp them. #[instrument(level = "trace", skip_all)] - pub fn internal_migrate_or_create_ignore_attrs( + fn internal_migrate_or_create_ignore_attrs( &mut self, mut e: Entry, attrs: &[Attribute], @@ -294,6 +302,75 @@ impl QueryServerWriteTransaction<'_> { } } + /// Migration domain level 7 to 8 (1.4.0) + #[instrument(level = "info", skip_all)] + pub(crate) fn migrate_domain_7_to_8(&mut self) -> Result<(), OperationError> { + if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_9 { + error!("Unable to raise domain level from 8 to 9."); + return Err(OperationError::MG0004DomainLevelInDevelopment); + } + + // =========== Apply changes ============== + self.internal_migrate_or_create_batch( + "phase 1 - schema attrs", + migration_data::dl8::phase_1_schema_attrs(), + )?; + + self.internal_migrate_or_create_batch( + "phase 2 - schema classes", + migration_data::dl8::phase_2_schema_classes(), + )?; + + // Reload for the new schema. + self.reload()?; + + // Reindex? + self.reindex(false)?; + + // Set Phase + self.set_phase(ServerPhase::SchemaReady); + + self.internal_migrate_or_create_batch( + "phase 3 - key provider", + migration_data::dl8::phase_3_key_provider(), + )?; + + // Reload for the new key providers + self.reload()?; + + self.internal_migrate_or_create_batch( + "phase 4 - system entries", + migration_data::dl8::phase_4_system_entries(), + )?; + + // Reload for the new system entries + self.reload()?; + + // Domain info is now ready and reloaded, we can proceed. + self.set_phase(ServerPhase::DomainInfoReady); + + // Bring up the IDM entries. + self.internal_migrate_or_create_batch( + "phase 5 - builtin admin entries", + migration_data::dl8::phase_5_builtin_admin_entries()?, + )?; + + self.internal_migrate_or_create_batch( + "phase 6 - builtin not admin entries", + migration_data::dl8::phase_6_builtin_non_admin_entries()?, + )?; + + self.internal_migrate_or_create_batch( + "phase 7 - builtin access control profiles", + migration_data::dl8::phase_7_builtin_access_control_profiles(), + )?; + + // Reload for all new access controls. + self.reload()?; + + Ok(()) + } + /// Migration domain level 8 to 9 (1.5.0) #[instrument(level = "info", skip_all)] pub(crate) fn migrate_domain_8_to_9(&mut self) -> Result<(), OperationError> { @@ -303,39 +380,61 @@ impl QueryServerWriteTransaction<'_> { } // =========== Apply changes ============== + self.internal_migrate_or_create_batch( + "phase 1 - schema attrs", + migration_data::dl9::phase_1_schema_attrs(), + )?; - // Now update schema - let idm_schema_changes = [ - SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(), - SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(), - SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(), - SCHEMA_CLASS_DOMAIN_INFO_DL9.clone().into(), - ]; - - idm_schema_changes - .into_iter() - .try_for_each(|entry| self.internal_migrate_or_create(entry)) - .map_err(|err| { - error!(?err, "migrate_domain_8_to_9 -> Error"); - err - })?; + self.internal_migrate_or_create_batch( + "phase 2 - schema classes", + migration_data::dl9::phase_2_schema_classes(), + )?; + // Reload for the new schema. self.reload()?; - let idm_data = [ - IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(), - IDM_ACP_GROUP_MANAGE_DL9.clone().into(), - IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(), - ]; + // Reindex? + self.reindex(false)?; - idm_data - .into_iter() - .try_for_each(|entry| self.internal_migrate_or_create(entry)) - .map_err(|err| { - error!(?err, "migrate_domain_8_to_9 -> Error"); - err - })?; + // Set Phase + self.set_phase(ServerPhase::SchemaReady); + self.internal_migrate_or_create_batch( + "phase 3 - key provider", + migration_data::dl9::phase_3_key_provider(), + )?; + + // Reload for the new key providers + self.reload()?; + + self.internal_migrate_or_create_batch( + "phase 4 - system entries", + migration_data::dl9::phase_4_system_entries(), + )?; + + // Reload for the new system entries + self.reload()?; + + // Domain info is now ready and reloaded, we can proceed. + self.set_phase(ServerPhase::DomainInfoReady); + + // Bring up the IDM entries. + self.internal_migrate_or_create_batch( + "phase 5 - builtin admin entries", + migration_data::dl9::phase_5_builtin_admin_entries()?, + )?; + + self.internal_migrate_or_create_batch( + "phase 6 - builtin not admin entries", + migration_data::dl9::phase_6_builtin_non_admin_entries()?, + )?; + + self.internal_migrate_or_create_batch( + "phase 7 - builtin access control profiles", + migration_data::dl9::phase_7_builtin_access_control_profiles(), + )?; + + // Reload for all new access controls. self.reload()?; Ok(()) @@ -350,58 +449,7 @@ impl QueryServerWriteTransaction<'_> { debug_assert!(*self.phase >= ServerPhase::SchemaReady); - let idm_data = [ - IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(), - IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone().into(), - IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone().into(), - IDM_ACP_ACP_MANAGE_V1.clone().into(), - IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone().into(), - IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone().into(), - IDM_ACP_APPLICATION_MANAGE_DL8.clone().into(), - IDM_ACP_DOMAIN_ADMIN_DL8.clone().into(), - IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone().into(), - IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone().into(), - IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone().into(), - IDM_ACP_GROUP_MANAGE_DL6.clone().into(), - IDM_ACP_GROUP_READ_V1.clone().into(), - IDM_ACP_GROUP_UNIX_MANAGE_V1.clone().into(), - IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone().into(), - IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone().into(), - IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), - IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 - .clone() - .into(), - IDM_ACP_MAIL_SERVERS_DL8.clone().into(), - IDM_ACP_OAUTH2_MANAGE_DL7.clone().into(), - IDM_ACP_PEOPLE_CREATE_DL6.clone().into(), - IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone().into(), - IDM_ACP_PEOPLE_DELETE_V1.clone().into(), - IDM_ACP_PEOPLE_MANAGE_V1.clone().into(), - IDM_ACP_PEOPLE_PII_MANAGE_V1.clone().into(), - IDM_ACP_PEOPLE_PII_READ_V1.clone().into(), - IDM_ACP_PEOPLE_READ_V1.clone().into(), - IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone().into(), - IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone().into(), - IDM_ACP_RADIUS_SERVERS_V1.clone().into(), - IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone().into(), - IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone().into(), - IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone().into(), - IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone().into(), - IDM_ACP_SELF_NAME_WRITE_DL7.clone().into(), - IDM_ACP_SELF_READ_DL8.clone().into(), - IDM_ACP_SELF_WRITE_DL8.clone().into(), - IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone().into(), - IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone().into(), - IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1 - .clone() - .into(), - IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone().into(), - IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone().into(), - IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone().into(), - IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1 - .clone() - .into(), - ]; + let idm_data = migration_data::dl9::phase_7_builtin_access_control_profiles(); idm_data .into_iter() @@ -425,21 +473,62 @@ impl QueryServerWriteTransaction<'_> { } // =========== Apply changes ============== + self.internal_migrate_or_create_batch( + "phase 1 - schema attrs", + migration_data::dl10::phase_1_schema_attrs(), + )?; - // Now update schema - let idm_schema_changes = [ - SCHEMA_ATTR_DENIED_NAME_DL10.clone().into(), - SCHEMA_CLASS_DOMAIN_INFO_DL10.clone().into(), - SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES.clone().into(), - ]; + self.internal_migrate_or_create_batch( + "phase 2 - schema classes", + migration_data::dl10::phase_2_schema_classes(), + )?; - idm_schema_changes - .into_iter() - .try_for_each(|entry| self.internal_migrate_or_create(entry)) - .map_err(|err| { - error!(?err, "migrate_domain_9_to_10 -> Error"); - err - })?; + // Reload for the new schema. + self.reload()?; + + // Since we just loaded in a ton of schema, lets reindex it incase we added + // new indexes, or this is a bootstrap and we have no indexes yet. + self.reindex(false)?; + + // Set Phase + // Indicate the schema is now ready, which allows dyngroups to work when they + // are created in the next phase of migrations. + self.set_phase(ServerPhase::SchemaReady); + + self.internal_migrate_or_create_batch( + "phase 3 - key provider", + migration_data::dl10::phase_3_key_provider(), + )?; + + // Reload for the new key providers + self.reload()?; + + self.internal_migrate_or_create_batch( + "phase 4 - system entries", + migration_data::dl10::phase_4_system_entries(), + )?; + + // Reload for the new system entries + self.reload()?; + + // Domain info is now ready and reloaded, we can proceed. + self.set_phase(ServerPhase::DomainInfoReady); + + // Bring up the IDM entries. + self.internal_migrate_or_create_batch( + "phase 5 - builtin admin entries", + migration_data::dl10::phase_5_builtin_admin_entries()?, + )?; + + self.internal_migrate_or_create_batch( + "phase 6 - builtin not admin entries", + migration_data::dl10::phase_6_builtin_non_admin_entries()?, + )?; + + self.internal_migrate_or_create_batch( + "phase 7 - builtin access control profiles", + migration_data::dl10::phase_7_builtin_access_control_profiles(), + )?; self.reload()?; @@ -458,7 +547,7 @@ impl QueryServerWriteTransaction<'_> { } #[instrument(level = "info", skip_all)] - pub fn initialise_schema_core(&mut self) -> Result<(), OperationError> { + pub(crate) fn initialise_schema_core(&mut self) -> Result<(), OperationError> { admin_debug!("initialise_schema_core -> start ..."); // Load in all the "core" schema, that we already have in "memory". let entries = self.schema.to_entries(); @@ -479,320 +568,6 @@ impl QueryServerWriteTransaction<'_> { debug_assert!(r.is_ok()); r } - - #[instrument(level = "info", skip_all)] - pub fn initialise_schema_idm(&mut self) -> Result<(), OperationError> { - admin_debug!("initialise_schema_idm -> start ..."); - - // ⚠️ DOMAIN LEVEL 1 SCHEMA ATTRIBUTES ⚠️ - // Future schema attributes need to be added via migrations. - // - // DO NOT MODIFY THIS DEFINITION - let idm_schema_attrs = [ - SCHEMA_ATTR_SYNC_CREDENTIAL_PORTAL.clone().into(), - SCHEMA_ATTR_SYNC_YIELD_AUTHORITY.clone().into(), - ]; - - let r: Result<(), _> = idm_schema_attrs - .into_iter() - .try_for_each(|entry| self.internal_migrate_or_create(entry)); - - if r.is_err() { - error!(res = ?r, "initialise_schema_idm -> Error"); - } - debug_assert!(r.is_ok()); - - // ⚠️ DOMAIN LEVEL 1 SCHEMA ATTRIBUTES ⚠️ - // Future schema classes need to be added via migrations. - // - // DO NOT MODIFY THIS DEFINITION - let idm_schema: Vec = vec![ - // SCHEMA_ATTR_MAIL.clone().into(), - SCHEMA_ATTR_ACCOUNT_EXPIRE.clone().into(), - SCHEMA_ATTR_ACCOUNT_VALID_FROM.clone().into(), - SCHEMA_ATTR_API_TOKEN_SESSION.clone().into(), - SCHEMA_ATTR_AUTH_SESSION_EXPIRY.clone().into(), - SCHEMA_ATTR_AUTH_PRIVILEGE_EXPIRY.clone().into(), - SCHEMA_ATTR_AUTH_PASSWORD_MINIMUM_LENGTH.clone().into(), - SCHEMA_ATTR_BADLIST_PASSWORD.clone().into(), - SCHEMA_ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN.clone().into(), - SCHEMA_ATTR_ATTESTED_PASSKEYS.clone().into(), - // SCHEMA_ATTR_DISPLAYNAME.clone().into(), - SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(), - SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(), - SCHEMA_ATTR_DOMAIN_NAME.clone().into(), - SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(), - SCHEMA_ATTR_DOMAIN_SSID.clone().into(), - SCHEMA_ATTR_DOMAIN_TOKEN_KEY.clone().into(), - SCHEMA_ATTR_DOMAIN_UUID.clone().into(), - SCHEMA_ATTR_DYNGROUP_FILTER.clone().into(), - SCHEMA_ATTR_EC_KEY_PRIVATE.clone().into(), - SCHEMA_ATTR_ES256_PRIVATE_KEY_DER.clone().into(), - SCHEMA_ATTR_FERNET_PRIVATE_KEY_STR.clone().into(), - SCHEMA_ATTR_GIDNUMBER.clone().into(), - SCHEMA_ATTR_GRANT_UI_HINT.clone().into(), - SCHEMA_ATTR_JWS_ES256_PRIVATE_KEY.clone().into(), - // SCHEMA_ATTR_LEGALNAME.clone().into(), - SCHEMA_ATTR_LOGINSHELL.clone().into(), - SCHEMA_ATTR_NAME_HISTORY.clone().into(), - SCHEMA_ATTR_NSUNIQUEID.clone().into(), - SCHEMA_ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE - .clone() - .into(), - SCHEMA_ATTR_OAUTH2_CONSENT_SCOPE_MAP.clone().into(), - SCHEMA_ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE.clone().into(), - SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_BASIC_SECRET.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_IMPLICIT_SCOPES.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_NAME.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_ORIGIN_LANDING.clone().into(), - // SCHEMA_ATTR_OAUTH2_RS_ORIGIN.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_SCOPE_MAP.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_SUP_SCOPE_MAP.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_TOKEN_KEY.clone().into(), - SCHEMA_ATTR_OAUTH2_SESSION.clone().into(), - SCHEMA_ATTR_PASSKEYS.clone().into(), - SCHEMA_ATTR_PRIMARY_CREDENTIAL.clone().into(), - SCHEMA_ATTR_PRIVATE_COOKIE_KEY.clone().into(), - SCHEMA_ATTR_RADIUS_SECRET.clone().into(), - SCHEMA_ATTR_RS256_PRIVATE_KEY_DER.clone().into(), - SCHEMA_ATTR_SSH_PUBLICKEY.clone().into(), - SCHEMA_ATTR_SYNC_COOKIE.clone().into(), - SCHEMA_ATTR_SYNC_TOKEN_SESSION.clone().into(), - SCHEMA_ATTR_UNIX_PASSWORD.clone().into(), - SCHEMA_ATTR_USER_AUTH_TOKEN_SESSION.clone().into(), - SCHEMA_ATTR_DENIED_NAME.clone().into(), - SCHEMA_ATTR_CREDENTIAL_TYPE_MINIMUM.clone().into(), - SCHEMA_ATTR_WEBAUTHN_ATTESTATION_CA_LIST.clone().into(), - // DL4 - SCHEMA_ATTR_OAUTH2_RS_CLAIM_MAP_DL4.clone().into(), - SCHEMA_ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT_DL4 - .clone() - .into(), - // DL5 - // DL6 - SCHEMA_ATTR_LIMIT_SEARCH_MAX_RESULTS_DL6.clone().into(), - SCHEMA_ATTR_LIMIT_SEARCH_MAX_FILTER_TEST_DL6.clone().into(), - SCHEMA_ATTR_KEY_INTERNAL_DATA_DL6.clone().into(), - SCHEMA_ATTR_KEY_PROVIDER_DL6.clone().into(), - SCHEMA_ATTR_KEY_ACTION_ROTATE_DL6.clone().into(), - SCHEMA_ATTR_KEY_ACTION_REVOKE_DL6.clone().into(), - SCHEMA_ATTR_KEY_ACTION_IMPORT_JWS_ES256_DL6.clone().into(), - // DL7 - SCHEMA_ATTR_PATCH_LEVEL_DL7.clone().into(), - SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7.clone().into(), - SCHEMA_ATTR_REFERS_DL7.clone().into(), - SCHEMA_ATTR_CERTIFICATE_DL7.clone().into(), - SCHEMA_ATTR_OAUTH2_RS_ORIGIN_DL7.clone().into(), - SCHEMA_ATTR_OAUTH2_STRICT_REDIRECT_URI_DL7.clone().into(), - SCHEMA_ATTR_MAIL_DL7.clone().into(), - SCHEMA_ATTR_LEGALNAME_DL7.clone().into(), - SCHEMA_ATTR_DISPLAYNAME_DL7.clone().into(), - // DL8 - SCHEMA_ATTR_LINKED_GROUP_DL8.clone().into(), - SCHEMA_ATTR_APPLICATION_PASSWORD_DL8.clone().into(), - SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK_DL8.clone().into(), - ]; - - let r = idm_schema - .into_iter() - // Each item individually logs it's result - .try_for_each(|entry| self.internal_migrate_or_create(entry)); - - if r.is_err() { - error!(res = ?r, "initialise_schema_idm -> Error"); - } - - debug_assert!(r.is_ok()); - - // ⚠️ DOMAIN LEVEL 1 SCHEMA CLASSES ⚠️ - // Future schema classes need to be added via migrations. - // - // DO NOT MODIFY THIS DEFINITION - let idm_schema_classes_dl1: Vec = vec![ - SCHEMA_CLASS_DYNGROUP.clone().into(), - SCHEMA_CLASS_ORGPERSON.clone().into(), - SCHEMA_CLASS_POSIXACCOUNT.clone().into(), - SCHEMA_CLASS_POSIXGROUP.clone().into(), - SCHEMA_CLASS_SYSTEM_CONFIG.clone().into(), - // DL4 - SCHEMA_CLASS_OAUTH2_RS_PUBLIC_DL4.clone().into(), - // DL5 - // SCHEMA_CLASS_PERSON_DL5.clone().into(), - SCHEMA_CLASS_ACCOUNT_DL5.clone().into(), - // SCHEMA_CLASS_OAUTH2_RS_DL5.clone().into(), - SCHEMA_CLASS_OAUTH2_RS_BASIC_DL5.clone().into(), - // DL6 - // SCHEMA_CLASS_ACCOUNT_POLICY_DL6.clone().into(), - // SCHEMA_CLASS_SERVICE_ACCOUNT_DL6.clone().into(), - // SCHEMA_CLASS_SYNC_ACCOUNT_DL6.clone().into(), - SCHEMA_CLASS_GROUP_DL6.clone().into(), - SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(), - SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(), - SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(), - SCHEMA_CLASS_KEY_OBJECT_JWT_ES256_DL6.clone().into(), - SCHEMA_CLASS_KEY_OBJECT_JWE_A128GCM_DL6.clone().into(), - SCHEMA_CLASS_KEY_OBJECT_INTERNAL_DL6.clone().into(), - // SCHEMA_CLASS_DOMAIN_INFO_DL6.clone().into(), - // DL7 - // SCHEMA_CLASS_DOMAIN_INFO_DL7.clone().into(), - SCHEMA_CLASS_SERVICE_ACCOUNT_DL7.clone().into(), - SCHEMA_CLASS_SYNC_ACCOUNT_DL7.clone().into(), - SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(), - SCHEMA_CLASS_OAUTH2_RS_DL7.clone().into(), - // DL8 - SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(), - SCHEMA_CLASS_APPLICATION_DL8.clone().into(), - SCHEMA_CLASS_PERSON_DL8.clone().into(), - SCHEMA_CLASS_DOMAIN_INFO_DL8.clone().into(), - ]; - - let r: Result<(), _> = idm_schema_classes_dl1 - .into_iter() - .try_for_each(|entry| self.internal_migrate_or_create(entry)); - - if r.is_err() { - error!(res = ?r, "initialise_schema_idm -> Error"); - } - debug_assert!(r.is_ok()); - - debug!("initialise_schema_idm -> Ok!"); - - r - } - - #[instrument(level = "info", skip_all)] - /// This function is idempotent, runs all the startup functionality and checks - pub fn initialise_domain_info(&mut self) -> Result<(), OperationError> { - // Configure the default key provider. This needs to exist *before* the - // domain info! - self.internal_migrate_or_create(E_KEY_PROVIDER_INTERNAL_DL6.clone()) - .and_then(|_| self.reload()) - .map_err(|err| { - error!(?err, "initialise_domain_info::E_KEY_PROVIDER_INTERNAL_DL6"); - debug_assert!(false); - err - })?; - - self.internal_migrate_or_create(E_SYSTEM_INFO_V1.clone()) - .and_then(|_| self.internal_migrate_or_create(E_DOMAIN_INFO_DL6.clone())) - .and_then(|_| self.internal_migrate_or_create(E_SYSTEM_CONFIG_V1.clone())) - .map_err(|err| { - error!(?err, "initialise_domain_info"); - debug_assert!(false); - err - }) - } - - #[instrument(level = "info", skip_all)] - /// This function is idempotent, runs all the startup functionality and checks - pub fn initialise_idm(&mut self) -> Result<(), OperationError> { - // The domain info now exists, we should be able to do these migrations as they will - // cause SPN regenerations to occur - - // Delete entries that no longer need to exist. - // TODO: Shouldn't this be a migration? - // Check the admin object exists (migrations). - // Create the default idm_admin group. - let admin_entries: Vec = idm_builtin_admin_entries()?; - let res: Result<(), _> = admin_entries - .into_iter() - // Each item individually logs it's result - .try_for_each(|ent| self.internal_migrate_or_create(ent)); - if res.is_ok() { - debug!("initialise_idm p1 -> result Ok!"); - } else { - error!(?res, "initialise_idm p1 -> result"); - } - debug_assert!(res.is_ok()); - res?; - - let res: Result<(), _> = idm_builtin_non_admin_groups() - .into_iter() - .try_for_each(|e| self.internal_migrate_or_create(e.clone().try_into()?)); - if res.is_ok() { - debug!("initialise_idm p2 -> result Ok!"); - } else { - error!(?res, "initialise_idm p2 -> result"); - } - debug_assert!(res.is_ok()); - res?; - - // ⚠️ DOMAIN LEVEL 1 ENTRIES ⚠️ - // Future entries need to be added via migrations. - // - // DO NOT MODIFY THIS DEFINITION - let idm_entries: Vec = vec![ - // Built in access controls. - IDM_ACP_RECYCLE_BIN_SEARCH_V1.clone(), - IDM_ACP_RECYCLE_BIN_REVIVE_V1.clone(), - IDM_ACP_SCHEMA_WRITE_ATTRS_V1.clone(), - IDM_ACP_SCHEMA_WRITE_CLASSES_V1.clone(), - IDM_ACP_ACP_MANAGE_V1.clone(), - IDM_ACP_GROUP_ENTRY_MANAGED_BY_MODIFY_V1.clone(), - IDM_ACP_GROUP_ENTRY_MANAGER_V1.clone(), - IDM_ACP_SYNC_ACCOUNT_MANAGE_V1.clone(), - IDM_ACP_RADIUS_SERVERS_V1.clone(), - IDM_ACP_RADIUS_SECRET_MANAGE_V1.clone(), - IDM_ACP_PEOPLE_SELF_WRITE_MAIL_V1.clone(), - // IDM_ACP_SELF_READ_V1.clone(), - // IDM_ACP_SELF_WRITE_V1.clone(), - IDM_ACP_ACCOUNT_SELF_WRITE_V1.clone(), - // IDM_ACP_SELF_NAME_WRITE_V1.clone(), - IDM_ACP_ALL_ACCOUNTS_POSIX_READ_V1.clone(), - IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1.clone(), - IDM_ACP_GROUP_UNIX_MANAGE_V1.clone(), - IDM_ACP_HP_GROUP_UNIX_MANAGE_V1.clone(), - IDM_ACP_GROUP_READ_V1.clone(), - IDM_ACP_ACCOUNT_UNIX_EXTEND_V1.clone(), - IDM_ACP_PEOPLE_PII_READ_V1.clone(), - IDM_ACP_PEOPLE_PII_MANAGE_V1.clone(), - IDM_ACP_PEOPLE_READ_V1.clone(), - IDM_ACP_PEOPLE_MANAGE_V1.clone(), - IDM_ACP_PEOPLE_DELETE_V1.clone(), - IDM_ACP_PEOPLE_CREDENTIAL_RESET_V1.clone(), - IDM_ACP_HP_PEOPLE_CREDENTIAL_RESET_V1.clone(), - IDM_ACP_SERVICE_ACCOUNT_CREATE_V1.clone(), - IDM_ACP_SERVICE_ACCOUNT_DELETE_V1.clone(), - IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGER_V1.clone(), - IDM_ACP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1.clone(), - IDM_ACP_HP_SERVICE_ACCOUNT_ENTRY_MANAGED_BY_MODIFY_V1.clone(), - IDM_ACP_SERVICE_ACCOUNT_MANAGE_V1.clone(), - // DL4 - // DL5 - // IDM_ACP_OAUTH2_MANAGE_DL5.clone(), - // DL6 - // IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone(), - IDM_ACP_PEOPLE_CREATE_DL6.clone(), - IDM_ACP_GROUP_MANAGE_DL6.clone(), - IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone(), - // IDM_ACP_DOMAIN_ADMIN_DL6.clone(), - // DL7 - // IDM_ACP_SELF_WRITE_DL7.clone(), - IDM_ACP_SELF_NAME_WRITE_DL7.clone(), - IDM_ACP_HP_CLIENT_CERTIFICATE_MANAGER_DL7.clone(), - IDM_ACP_OAUTH2_MANAGE_DL7.clone(), - // DL8 - IDM_ACP_SELF_READ_DL8.clone(), - IDM_ACP_SELF_WRITE_DL8.clone(), - IDM_ACP_APPLICATION_MANAGE_DL8.clone(), - IDM_ACP_APPLICATION_ENTRY_MANAGER_DL8.clone(), - IDM_ACP_MAIL_SERVERS_DL8.clone(), - IDM_ACP_DOMAIN_ADMIN_DL8.clone(), - IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL8.clone(), - ]; - - let res: Result<(), _> = idm_entries - .into_iter() - .try_for_each(|entry| self.internal_migrate_or_create(entry.into())); - if res.is_ok() { - admin_debug!("initialise_idm p3 -> result Ok!"); - } else { - admin_error!(?res, "initialise_idm p3 -> result"); - } - debug_assert!(res.is_ok()); - res - } } impl QueryServerReadTransaction<'_> { diff --git a/server/lib/src/server/mod.rs b/server/lib/src/server/mod.rs index 11f914ca6..8c6f605be 100644 --- a/server/lib/src/server/mod.rs +++ b/server/lib/src/server/mod.rs @@ -2420,8 +2420,17 @@ impl<'a> QueryServerWriteTransaction<'a> { debug!(domain_previous_version = ?previous_version, domain_target_version = ?domain_info_version); debug!(domain_previous_patch_level = ?previous_patch_level, domain_target_patch_level = ?domain_info_patch_level); - // We have to check for DL0 since that's the initialisation level. - if previous_version < DOMAIN_MIN_REMIGRATION_LEVEL && previous_version != DOMAIN_LEVEL_0 { + // We have to check for DL0 since that's the initialisation level. If we are at DL0 then + // the server was just brought up and there are no other actions to take since we are + // now at TGT level. + if previous_version == DOMAIN_LEVEL_0 { + debug!( + "Server was just brought up, skipping migrations as we are already at target level" + ); + return Ok(()); + } + + if previous_version < DOMAIN_MIN_REMIGRATION_LEVEL { error!("UNABLE TO PROCEED. You are attempting a Skip update which is NOT SUPPORTED. You must upgrade one-version of Kanidm at a time."); error!("For more see: https://kanidm.github.io/kanidm/stable/support.html#upgrade-policy and https://kanidm.github.io/kanidm/stable/server_updates.html"); error!(domain_previous_version = ?previous_version, domain_target_version = ?domain_info_version); @@ -2434,7 +2443,10 @@ impl<'a> QueryServerWriteTransaction<'a> { self.migrate_domain_8_to_9()?; } - if previous_patch_level < PATCH_LEVEL_2 && domain_info_patch_level >= PATCH_LEVEL_2 { + if previous_patch_level < PATCH_LEVEL_2 + && domain_info_patch_level >= PATCH_LEVEL_2 + && domain_info_version == DOMAIN_LEVEL_9 + { self.migrate_domain_patch_level_2()?; } @@ -2573,7 +2585,10 @@ impl<'a> QueryServerWriteTransaction<'a> { } fn set_phase(&mut self, phase: ServerPhase) { - *self.phase = phase + // Phase changes are one way + if phase > *self.phase { + *self.phase = phase + } } pub(crate) fn get_phase(&mut self) -> ServerPhase { diff --git a/server/lib/src/server/modify.rs b/server/lib/src/server/modify.rs index 092884828..561fb951d 100644 --- a/server/lib/src/server/modify.rs +++ b/server/lib/src/server/modify.rs @@ -615,9 +615,11 @@ mod tests { Err(OperationError::EmptyRequest) ); + let idm_admin = server_txn.internal_search_uuid(UUID_IDM_ADMIN).unwrap(); + // Mod changes no objects - let me_nochg = ModifyEvent::new_impersonate_entry_ser( - BUILTIN_ACCOUNT_IDM_ADMIN.clone(), + let me_nochg = ModifyEvent::new_impersonate_entry( + idm_admin, filter!(f_eq( Attribute::Name, PartialValue::new_iname("flarbalgarble") diff --git a/server/testkit/examples/enumerating_access.rs b/server/testkit/defunct_examples/enumerating_access.rs similarity index 94% rename from server/testkit/examples/enumerating_access.rs rename to server/testkit/defunct_examples/enumerating_access.rs index 56c4dce68..5a3bf6691 100644 --- a/server/testkit/examples/enumerating_access.rs +++ b/server/testkit/defunct_examples/enumerating_access.rs @@ -4,7 +4,9 @@ //! use kanidmd_lib::constants::entries::Attribute; -use kanidmd_lib::constants::groups::{idm_builtin_admin_groups, idm_builtin_non_admin_groups}; +use kanidmd_lib::migration_data::current::{ + phase_5_builtin_admin_entries, phase_6_builtin_non_admin_entries +}; use kanidmd_lib::prelude::{builtin_accounts, EntryInitNew}; use petgraph::graphmap::{AllEdges, GraphMap, NodeTrait}; use petgraph::Directed; @@ -106,8 +108,8 @@ async fn enumerate_default_groups(/*_client: KanidmClient*/) { graph.add_node(account.uuid); }); - let mut groups = idm_builtin_admin_groups(); - groups.extend(idm_builtin_non_admin_groups()); + let mut groups = phase_5_builtin_admin_entries(); + groups.extend(phase_6_builtin_non_admin_entries()); groups.into_iter().for_each(|group| { uuidmap.insert(group.uuid, group.clone().try_into().unwrap()); diff --git a/server/testkit/src/lib.rs b/server/testkit/src/lib.rs index 56bca39b4..c9bf0453c 100644 --- a/server/testkit/src/lib.rs +++ b/server/testkit/src/lib.rs @@ -18,7 +18,7 @@ use kanidm_client::{KanidmClient, KanidmClientBuilder}; use kanidm_proto::internal::{Filter, Modify, ModifyList}; use kanidmd_core::config::{Configuration, IntegrationTestConfig}; use kanidmd_core::{create_server_core, CoreHandle}; -use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1}; +use kanidmd_lib::prelude::Attribute; use tokio::task; pub const ADMIN_TEST_USER: &str = "admin"; @@ -385,7 +385,7 @@ pub async fn login_put_admin_idm_admins(rsclient: &KanidmClient) { #[allow(clippy::expect_used)] rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &[ADMIN_TEST_USER]) + .idm_group_add_members("system_admins", &[ADMIN_TEST_USER]) .await .expect("Failed to add admin user to idm_admins") } diff --git a/server/testkit/tests/oauth2_device_flow.rs b/server/testkit/tests/oauth2_device_flow.rs index d9e035d52..22feee9cd 100644 --- a/server/testkit/tests/oauth2_device_flow.rs +++ b/server/testkit/tests/oauth2_device_flow.rs @@ -12,10 +12,9 @@ use kanidm_proto::oauth2::{ AccessTokenRequest, AccessTokenResponse, AuthorisationResponse, GrantTypeReq, }; +use kanidmd_lib::constants::NAME_IDM_ALL_ACCOUNTS; use kanidmd_lib::prelude::uri::{OAUTH2_AUTHORISE_DEVICE, OAUTH2_TOKEN_ENDPOINT}; -use kanidmd_lib::prelude::{ - Attribute, IDM_ALL_ACCOUNTS, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID, OAUTH2_SCOPE_READ, -}; +use kanidmd_lib::prelude::{Attribute, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID, OAUTH2_SCOPE_READ}; use kanidmd_testkit::{ assert_no_cache, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER, IDM_ADMIN_TEST_PASSWORD, IDM_ADMIN_TEST_USER, NOT_ADMIN_TEST_EMAIL, NOT_ADMIN_TEST_PASSWORD, NOT_ADMIN_TEST_USERNAME, @@ -159,7 +158,7 @@ async fn oauth2_device_flow(rsclient: KanidmClient) { rsclient .idm_oauth2_rs_update_scope_map( TEST_INTEGRATION_RS_ID, - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, vec![OAUTH2_SCOPE_READ, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID], ) .await @@ -168,7 +167,7 @@ async fn oauth2_device_flow(rsclient: KanidmClient) { rsclient .idm_oauth2_rs_update_sup_scope_map( TEST_INTEGRATION_RS_ID, - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, vec![ADMIN_TEST_USER], ) .await @@ -179,7 +178,7 @@ async fn oauth2_device_flow(rsclient: KanidmClient) { .idm_oauth2_rs_update_claim_map( TEST_INTEGRATION_RS_ID, "test_claim", - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, &["claim_a".to_string(), "claim_b".to_string()], ) .await diff --git a/server/testkit/tests/oauth2_test.rs b/server/testkit/tests/oauth2_test.rs index faab08575..500745567 100644 --- a/server/testkit/tests/oauth2_test.rs +++ b/server/testkit/tests/oauth2_test.rs @@ -12,7 +12,8 @@ use kanidm_proto::oauth2::{ AccessTokenResponse, AccessTokenType, AuthorisationResponse, GrantTypeReq, OidcDiscoveryResponse, }; -use kanidmd_lib::prelude::{Attribute, IDM_ALL_ACCOUNTS}; +use kanidmd_lib::constants::NAME_IDM_ALL_ACCOUNTS; +use kanidmd_lib::prelude::Attribute; use oauth2_ext::PkceCodeChallenge; use reqwest::header::{HeaderValue, CONTENT_TYPE}; use reqwest::StatusCode; @@ -98,7 +99,7 @@ async fn test_oauth2_openid_basic_flow_impl( rsclient .idm_oauth2_rs_update_scope_map( TEST_INTEGRATION_RS_ID, - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, vec![OAUTH2_SCOPE_READ, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID], ) .await @@ -107,7 +108,7 @@ async fn test_oauth2_openid_basic_flow_impl( rsclient .idm_oauth2_rs_update_sup_scope_map( TEST_INTEGRATION_RS_ID, - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, vec![ADMIN_TEST_USER], ) .await @@ -627,7 +628,7 @@ async fn test_oauth2_openid_public_flow_impl( rsclient .idm_oauth2_rs_update_scope_map( TEST_INTEGRATION_RS_ID, - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, vec![OAUTH2_SCOPE_READ, OAUTH2_SCOPE_EMAIL, OAUTH2_SCOPE_OPENID], ) .await @@ -636,7 +637,7 @@ async fn test_oauth2_openid_public_flow_impl( rsclient .idm_oauth2_rs_update_sup_scope_map( TEST_INTEGRATION_RS_ID, - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, vec![ADMIN_TEST_USER], ) .await @@ -647,7 +648,7 @@ async fn test_oauth2_openid_public_flow_impl( .idm_oauth2_rs_update_claim_map( TEST_INTEGRATION_RS_ID, "test_claim", - IDM_ALL_ACCOUNTS.name, + NAME_IDM_ALL_ACCOUNTS, &["claim_a".to_string(), "claim_b".to_string()], ) .await diff --git a/server/testkit/tests/proto_v1_test.rs b/server/testkit/tests/proto_v1_test.rs index a07061bcb..577d14d30 100644 --- a/server/testkit/tests/proto_v1_test.rs +++ b/server/testkit/tests/proto_v1_test.rs @@ -3,6 +3,7 @@ use std::path::Path; use std::time::SystemTime; use kanidm_proto::constants::{ATTR_GIDNUMBER, KSESSIONID}; + use kanidm_proto::internal::{ ApiToken, CURegState, Filter, ImageValue, Modify, ModifyList, UatPurpose, UserAuthToken, }; @@ -10,10 +11,10 @@ use kanidm_proto::v1::{ AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthResponse, AuthState, AuthStep, Entry, }; +use kanidmd_lib::constants::{NAME_IDM_ADMINS, NAME_SYSTEM_ADMINS}; use kanidmd_lib::credential::totp::Totp; -use kanidmd_lib::prelude::{ - Attribute, BUILTIN_GROUP_IDM_ADMINS_V1, BUILTIN_GROUP_SYSTEM_ADMINS_V1, -}; + +use kanidmd_lib::prelude::Attribute; use tracing::{debug, trace}; use std::str::FromStr; @@ -144,10 +145,7 @@ async fn test_server_rest_group_read(rsclient: KanidmClient) { let g_list = rsclient.idm_group_list().await.unwrap(); assert!(!g_list.is_empty()); - let g = rsclient - .idm_group_get(BUILTIN_GROUP_IDM_ADMINS_V1.name) - .await - .unwrap(); + let g = rsclient.idm_group_get(NAME_IDM_ADMINS).await.unwrap(); assert!(g.is_some()); println!("{:?}", g); } @@ -165,7 +163,7 @@ async fn test_server_rest_group_lifecycle(rsclient: KanidmClient) { // Create a new group rsclient - .idm_group_create("demo_group", Some(BUILTIN_GROUP_IDM_ADMINS_V1.name)) + .idm_group_create("demo_group", Some(NAME_IDM_ADMINS)) .await .unwrap(); @@ -245,16 +243,13 @@ async fn test_server_rest_group_lifecycle(rsclient: KanidmClient) { assert_eq!(g_list_3.len(), g_list.len()); // Check we can get an exact group - let g = rsclient - .idm_group_get(BUILTIN_GROUP_IDM_ADMINS_V1.name) - .await - .unwrap(); + let g = rsclient.idm_group_get(NAME_IDM_ADMINS).await.unwrap(); assert!(g.is_some()); println!("{:?}", g); // They should have members let members = rsclient - .idm_group_get_members(BUILTIN_GROUP_IDM_ADMINS_V1.name) + .idm_group_get_members(NAME_IDM_ADMINS) .await .unwrap(); println!("{:?}", members); @@ -326,7 +321,7 @@ async fn test_server_radius_credential_lifecycle(rsclient: KanidmClient) { // All admin to create persons. rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -397,7 +392,7 @@ async fn test_server_rest_person_account_lifecycle(rsclient: KanidmClient) { // To enable the admin to actually make some of these changes, we have // to make them a people admin. NOT recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -551,7 +546,7 @@ async fn test_server_rest_posix_lifecycle(rsclient: KanidmClient) { assert!(res.is_ok()); // Not recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -571,7 +566,7 @@ async fn test_server_rest_posix_lifecycle(rsclient: KanidmClient) { // Extend the group with posix attrs rsclient - .idm_group_create("posix_group", Some(BUILTIN_GROUP_IDM_ADMINS_V1.name)) + .idm_group_create("posix_group", Some(NAME_IDM_ADMINS)) .await .unwrap(); rsclient @@ -676,7 +671,7 @@ async fn test_server_rest_posix_auth_lifecycle(rsclient: KanidmClient) { // Not recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -773,7 +768,7 @@ async fn test_server_rest_recycle_lifecycle(rsclient: KanidmClient) { // Not recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -826,7 +821,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) { assert!(res.is_ok()); rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -902,11 +897,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) { // Check that we can add scope maps and delete them. rsclient - .idm_oauth2_rs_update_scope_map( - "test_integration", - BUILTIN_GROUP_SYSTEM_ADMINS_V1.name, - vec!["a", "b"], - ) + .idm_oauth2_rs_update_scope_map("test_integration", NAME_SYSTEM_ADMINS, vec!["a", "b"]) .await .expect("Failed to create scope map"); @@ -921,11 +912,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) { // Check we can update a scope map rsclient - .idm_oauth2_rs_update_scope_map( - "test_integration", - BUILTIN_GROUP_SYSTEM_ADMINS_V1.name, - vec!["a", "b", "c"], - ) + .idm_oauth2_rs_update_scope_map("test_integration", NAME_SYSTEM_ADMINS, vec!["a", "b", "c"]) .await .expect("Failed to create scope map"); @@ -1009,7 +996,7 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) { // Check we can delete a scope map. rsclient - .idm_oauth2_rs_delete_scope_map("test_integration", BUILTIN_GROUP_SYSTEM_ADMINS_V1.name) + .idm_oauth2_rs_delete_scope_map("test_integration", NAME_SYSTEM_ADMINS) .await .expect("Failed to delete scope map"); @@ -1049,7 +1036,7 @@ async fn test_server_credential_update_session_pw(rsclient: KanidmClient) { // Not recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -1124,7 +1111,7 @@ async fn test_server_credential_update_session_totp_pw(rsclient: KanidmClient) { // Not recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -1253,7 +1240,7 @@ async fn setup_demo_account_passkey(rsclient: &KanidmClient) -> WebauthnAuthenti // Not recommended in production! rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); @@ -1409,7 +1396,7 @@ async fn test_server_api_token_lifecycle(rsclient: KanidmClient) { .idm_service_account_create( test_service_account_username, "Test Service", - BUILTIN_GROUP_IDM_ADMINS_V1.name, + NAME_IDM_ADMINS, ) .await .expect("Failed to create service account"); diff --git a/server/testkit/tests/scim_test.rs b/server/testkit/tests/scim_test.rs index b760406eb..674e546b5 100644 --- a/server/testkit/tests/scim_test.rs +++ b/server/testkit/tests/scim_test.rs @@ -2,7 +2,8 @@ use compact_jwt::{traits::JwsVerifiable, JwsCompact, JwsEs256Verifier, JwsVerifi use kanidm_client::KanidmClient; use kanidm_proto::internal::ScimSyncToken; use kanidm_proto::scim_v1::ScimEntryGetQuery; -use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1}; +use kanidmd_lib::constants::NAME_IDM_ADMINS; +use kanidmd_lib::prelude::Attribute; use kanidmd_testkit::{ADMIN_TEST_PASSWORD, ADMIN_TEST_USER}; use reqwest::header::HeaderValue; use std::str::FromStr; @@ -170,7 +171,7 @@ async fn test_scim_sync_entry_get(rsclient: KanidmClient) { // All admin to create persons. rsclient - .idm_group_add_members(BUILTIN_GROUP_IDM_ADMINS_V1.name, &["admin"]) + .idm_group_add_members(NAME_IDM_ADMINS, &["admin"]) .await .unwrap(); diff --git a/server/testkit/tests/unix.rs b/server/testkit/tests/unix.rs index 8381b4e69..f3ea98c6d 100644 --- a/server/testkit/tests/unix.rs +++ b/server/testkit/tests/unix.rs @@ -1,5 +1,5 @@ use kanidm_client::KanidmClient; -use kanidmd_lib::prelude::BUILTIN_GROUP_IDM_ADMINS_V1; +use kanidmd_lib::constants::NAME_IDM_ADMINS; use kanidmd_testkit::*; #[kanidmd_testkit::test] @@ -8,12 +8,7 @@ async fn account_id_unix_token(rsclient: KanidmClient) { create_user(&rsclient, "group_manager", "idm_group_manage_priv").await; // create test user without creating new groups - create_user( - &rsclient, - NOT_ADMIN_TEST_USERNAME, - BUILTIN_GROUP_IDM_ADMINS_V1.name, - ) - .await; + create_user(&rsclient, NOT_ADMIN_TEST_USERNAME, NAME_IDM_ADMINS).await; login_account(&rsclient, "group_manager").await; let response = rsclient