diff --git a/libs/sketching/src/lib.rs b/libs/sketching/src/lib.rs index 02e52651d..e405e383d 100644 --- a/libs/sketching/src/lib.rs +++ b/libs/sketching/src/lib.rs @@ -1,6 +1,6 @@ #![deny(warnings)] #![warn(unused_extern_crates)] - +#![allow(non_snake_case)] use num_enum::{IntoPrimitive, TryFromPrimitive}; use tracing_forest::util::*; use tracing_forest::Tag; diff --git a/server/lib/src/constants/acp.rs b/server/lib/src/constants/acp.rs index f22700902..b5c49dbc4 100644 --- a/server/lib/src/constants/acp.rs +++ b/server/lib/src/constants/acp.rs @@ -7,7 +7,11 @@ use crate::prelude::*; use crate::value::Value; use kanidm_proto::v1::Filter as ProtoFilter; -#[derive(Clone)] +lazy_static! { + pub static ref DEFAULT_TARGET_SCOPE: ProtoFilter = ProtoFilter::And(Vec::with_capacity(0)); +} + +#[derive(Clone, Debug)] /// Built-in Access Control Profile definitions pub struct BuiltinAcp { classes: Vec, @@ -17,12 +21,40 @@ pub struct BuiltinAcp { receiver_group: Uuid, target_scope: ProtoFilter, search_attrs: Vec, + modify_removed_attrs: Vec, + modify_classes: Vec, +} + +impl Default for BuiltinAcp { + fn default() -> Self { + Self { + classes: Default::default(), + name: Default::default(), + uuid: Default::default(), + description: Default::default(), + receiver_group: Default::default(), + search_attrs: Default::default(), + modify_removed_attrs: Default::default(), + modify_classes: Default::default(), + target_scope: DEFAULT_TARGET_SCOPE.clone(), // evals to matching nothing + } + } } impl From for EntryInitNew { fn from(value: BuiltinAcp) -> Self { let mut entry = EntryInitNew::default(); + if value.name.is_empty() { + panic!("Builtin ACP has no name! {:?}", value); + } + if value.classes.is_empty() { + panic!("Builtin ACP has no classes! {:?}", value); + } + if DEFAULT_TARGET_SCOPE.clone() == value.target_scope { + panic!("Builtin ACP has an invalid target_scope! {:?}", value); + } + value.classes.into_iter().for_each(|class| { entry.add_ava(ATTR_CLASS, class.to_value()); }); @@ -44,6 +76,12 @@ impl From for EntryInitNew { .map(|sa| sa.to_value()) .collect::>(), ); + value.modify_removed_attrs.into_iter().for_each(|attr| { + entry.add_ava(Attribute::AcpModifyRemovedAttr.as_ref(), attr.to_value()); + }); + value.modify_classes.into_iter().for_each(|class| { + entry.add_ava(Attribute::AcpModifyClass.as_ref(), class.to_value()); + }); entry } } @@ -67,35 +105,31 @@ lazy_static! { Attribute::Uuid, Attribute::LastModifiedCid, ], + ..Default::default() }; } lazy_static! { - pub static ref E_IDM_ADMINS_ACP_REVIVE_V1: EntryInitNew = entry_init!( - (ATTR_CLASS, EntryClass::Object.to_value()), - (ATTR_CLASS, EntryClass::AccessControlProfile.to_value()), - (ATTR_CLASS, EntryClass::AccessControlModify.to_value()), - (ATTR_NAME, Value::new_iname("idm_admins_acp_revive")), - (ATTR_UUID, Value::Uuid(UUID_IDM_ADMINS_ACP_REVIVE_V1)), - ( - Attribute::Description.as_ref(), - Value::new_utf8s("Builtin IDM admin recycle bin revive permission.") - ), - (ATTR_ACP_RECEIVER_GROUP, Value::Refer(UUID_SYSTEM_ADMINS)), - ( - ATTR_ACP_TARGET_SCOPE, - Value::JsonFilt(ProtoFilter::Eq( - ATTR_CLASS.to_string(), - ATTR_RECYCLED.to_string() - )) - ), - (ATTR_ACP_MODIFY_REMOVEDATTR, Attribute::Class.to_value()), - (ATTR_ACP_MODIFY_CLASS, EntryClass::Recycled.to_value()) - ); + pub static ref IDM_ADMINS_ACP_REVIVE_V1: BuiltinAcp = BuiltinAcp { + uuid: UUID_IDM_ADMINS_ACP_REVIVE_V1, + name: "idm_admins_acp_revive", + description: "Builtin IDM admin recycle bin revive permission.", + classes: vec![ + EntryClass::Object, + EntryClass::AccessControlProfile, + EntryClass::AccessControlModify, + ], + receiver_group: UUID_SYSTEM_ADMINS, + target_scope: ProtoFilter::Eq(ATTR_CLASS.to_string(), ATTR_RECYCLED.to_string()), + modify_removed_attrs: vec![Attribute::Class], + search_attrs: vec![], + modify_classes: vec![EntryClass::Recycled], + }; } lazy_static! { - pub static ref E_IDM_SELF_ACP_READ_V1: EntryInitNew = entry_init!( + pub static ref E_IDM_SELF_ACP_READ_V1: EntryInitNew = + entry_init!( (ATTR_CLASS, EntryClass::Object.to_value()), (ATTR_CLASS, EntryClass::AccessControlProfile.to_value()), (ATTR_CLASS, EntryClass::AccessControlSearch.to_value()), @@ -110,8 +144,7 @@ lazy_static! { (ATTR_ACP_RECEIVER_GROUP, Value::Refer(UUID_IDM_ALL_ACCOUNTS)), ( ATTR_ACP_TARGET_SCOPE, - Value::new_json_filter_s("\"self\"").expect("Invalid JSON filter") - // Value::JsonFilt(ProtoFilter::SelfUuid) + Value::JsonFilt(ProtoFilter::SelfUuid) ), (ATTR_ACP_SEARCH_ATTR, Attribute::Class.to_value()), (ATTR_ACP_SEARCH_ATTR, Attribute::Name.to_value()), diff --git a/server/lib/src/constants/entries.rs b/server/lib/src/constants/entries.rs index 61ef67509..1468af5f9 100644 --- a/server/lib/src/constants/entries.rs +++ b/server/lib/src/constants/entries.rs @@ -5,10 +5,11 @@ use std::fmt::Display; 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 kanidm_proto::constants::*; -use kanidm_proto::v1::{OperationError, UiHint}; +use kanidm_proto::v1::{Filter, OperationError, UiHint}; #[cfg(test)] use uuid::uuid; @@ -642,18 +643,22 @@ impl EntryClass { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] /// Built-in group definitions pub struct BuiltinGroup { pub name: &'static str, description: &'static str, - classes: Vec, uuid: uuid::Uuid, - member: uuid::Uuid, + members: Vec, + dyngroup: bool, + dyngroup_filter: Option, + extra_attributes: Vec<(Attribute, Value)>, } -impl From for EntryInitNew { - fn from(val: BuiltinGroup) -> Self { +impl TryFrom for EntryInitNew { + type Error = OperationError; + + fn try_from(val: BuiltinGroup) -> Result { let mut entry = EntryInitNew::new(); entry.add_ava(Attribute::Name.as_ref(), Value::new_iname(val.name)); @@ -661,604 +666,508 @@ impl From for EntryInitNew { Attribute::Description.as_ref(), Value::new_utf8s(val.description), ); - // classes + // classes for groups entry.set_ava( Attribute::Class.as_ref(), - val.classes + 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.as_ref(), EntryClass::DynGroup.to_value()); + match val.dyngroup_filter { + Some(filter) => { + entry.add_ava(Attribute::DynGroupFilter.as_ref(), Value::JsonFilt(filter)) + } + None => { + error!( + "No filter specified for dyngroup '{}' this is going to break things!", + val.name + ); + return Err(OperationError::FilterGeneration); + } + }; + } + entry.add_ava(Attribute::Uuid.as_ref(), Value::Uuid(val.uuid)); + entry.set_ava( + Attribute::Member.as_ref(), + val.members .into_iter() - .map(|class| class.to_value()) + .map(Value::Refer) .collect::>(), ); - entry.add_ava(Attribute::Uuid.as_ref(), Value::Uuid(val.uuid)); - entry.add_ava(Attribute::Member.as_ref(), Value::Refer(val.member)); - entry + // add any extra attributes + val.extra_attributes + .into_iter() + .for_each(|(attr, val)| entry.add_ava(attr.as_ref(), val)); + // all done! + Ok(entry) } } -/// Builtin System Admin account. -pub const JSON_ADMIN_V1: &str = r#"{ - "attrs": { - "class": ["account", "service_account", "memberof", "object"], - "name": ["admin"], - "uuid": ["00000000-0000-0000-0000-000000000000"], - "description": ["Builtin System Admin account."], - "displayname": ["System Administrator"] - } -}"#; - lazy_static! { - pub static ref E_ADMIN_V1: EntryInitNew = entry_init!( - (Attribute::Class.as_ref(), EntryClass::Account.to_value()), - (Attribute::Class.as_ref(), EntryClass::MemberOf.to_value()), - (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - ( - Attribute::Class.as_ref(), - EntryClass::ServiceAccount.to_value() - ), - (Attribute::Name.as_ref(), Value::new_iname("admin")), - (Attribute::Uuid.as_ref(), Value::Uuid(UUID_ADMIN)), - ( - Attribute::Description.as_ref(), - Value::new_utf8s("Builtin System Admin account.") - ), - ( - Attribute::DisplayName.as_ref(), - Value::new_utf8s("System Administrator") - ) - ); -} - -lazy_static! { - /// Builtin IDM Admin account. - pub static ref E_IDM_ADMIN_V1: EntryInitNew = entry_init!( - (Attribute::Class.as_ref(), EntryClass::Account.to_value()), - (Attribute::Class.as_ref(), EntryClass::MemberOf.to_value()), - (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - (Attribute::Class.as_ref(), EntryClass::ServiceAccount.to_value()), - (Attribute::Name.as_ref(), Value::new_iname("idm_admin")), - (Attribute::Uuid.as_ref(), Value::Uuid(UUID_IDM_ADMIN)), - ( - Attribute::Description.as_ref(), - Value::new_utf8s("Builtin IDM Admin account.") - ), - (Attribute::DisplayName.as_ref(), Value::new_utf8s("IDM Administrator")) - ); -} - -lazy_static! { - pub static ref IDM_ADMINS_V1: BuiltinGroup = BuiltinGroup { - name: "idm_admins", - description: "Builtin IDM Administrators Group.", + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_IDM_ADMIN: BuiltinAccount = BuiltinAccount { + // TODO: this really should be a "are you a service account or a person" enum classes: vec![ - EntryClass::Group, + EntryClass::Account, + EntryClass::ServiceAccount, + EntryClass::MemberOf, EntryClass::Object, ], - uuid: UUID_IDM_ADMINS, - member: UUID_IDM_ADMIN, + name: "idm_admin", + uuid: UUID_IDM_ADMIN, + description: "Builtin IDM Admin account.", + displayname: "IDM Administrator", }; - /// Builtin IDM Administrators Group. - pub static ref E_IDM_ADMINS_V1: EntryInitNew = IDM_ADMINS_V1.clone().into(); - // pub static ref E_IDM_ADMINS_V1: EntryInitNew = entry_init!( - // (Attribute::Class.as_ref(), EntryClass::Group.to_value()), - // (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - // (Attribute::Name.as_ref(), Value::new_iname("idm_admins")), - // (Attribute::Uuid.as_ref(), Value::Uuid(UUID_IDM_ADMINS)), - // ( - // Attribute::Description.as_ref(), - // Value::new_utf8s("Builtin IDM Administrators Group.") - // ), - // (Attribute::Member.as_ref(), Value::Refer(UUID_IDM_ADMIN)) - // ); -} -lazy_static! { - /// Builtin System Administrators Group. - pub static ref E_SYSTEM_ADMINS_V1: EntryInitNew = entry_init!( - (Attribute::Class.as_ref(), EntryClass::Group.to_value()), - (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - (Attribute::Name.as_ref(), Value::new_iname("system_admins")), - (Attribute::Uuid.as_ref(), Value::Uuid(UUID_SYSTEM_ADMINS)), - ( - Attribute::Description.as_ref(), - Value::new_utf8s("Builtin System Administrators Group.") - ), - (Attribute::Member.as_ref(), Value::Refer(UUID_ADMIN)) - ); -} + /// Builtin IDM Administrators Group. + pub static ref BUILTIN_GROUP_IDM_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_admins", + description: "Builtin IDM Administrators Group.", + uuid: UUID_IDM_ADMINS, + members: vec![UUID_IDM_ADMIN], + ..Default::default() + }; + + pub static ref BUILTIN_GROUP_SYSTEM_ADMINS_V1: BuiltinGroup = BuiltinGroup { + name: "system_admins", + description: "Builtin System Administrators Group.", + uuid: UUID_SYSTEM_ADMINS, + members: vec![BUILTIN_ACCOUNT_ADMIN.uuid], + ..Default::default() + }; // * People read managers -/// Builtin IDM Group for granting elevated people (personal data) read permissions. -pub const JSON_IDM_PEOPLE_READ_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_people_read_priv"], - "uuid": ["00000000-0000-0000-0000-000000000002"], - "description": ["Builtin IDM Group for granting elevated people (personal data) read permissions."], - "member": ["00000000-0000-0000-0000-000000000003"] - } -}"#; + /// Builtin IDM Group for granting elevated people (personal data) read permissions. + pub static ref IDM_PEOPLE_READ_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_people_read_priv", + description: "Builtin IDM Group for granting elevated people (personal data) read permissions.", + uuid: UUID_IDM_PEOPLE_READ_PRIV, + members: vec![UUID_IDM_PEOPLE_WRITE_PRIV], + ..Default::default() + }; + pub static ref IDM_PEOPLE_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_people_write_priv", + description: "Builtin IDM Group for granting elevated people (personal data) write permissions.", + uuid: UUID_IDM_PEOPLE_WRITE_PRIV, + members: vec![UUID_IDM_PEOPLE_MANAGE_PRIV,UUID_IDM_PEOPLE_EXTEND_PRIV], + ..Default::default() + }; // * People write managers -/// Builtin IDM Group for granting elevated people (personal data) write and lifecycle management permissions. -pub const JSON_IDM_PEOPLE_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_people_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000013"], - "description": ["Builtin IDM Group for granting elevated people (personal data) write and lifecycle management permissions."], - "member": [ - "00000000-0000-0000-0000-000000000001" - ] - } -}"#; + /// Builtin IDM Group for granting elevated people (personal data) write and lifecycle management permissions. + pub static ref IDM_PEOPLE_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_people_manage_priv", + description: "Builtin IDM Group for granting elevated people (personal data) write and lifecycle management permissions.", + uuid: UUID_IDM_PEOPLE_MANAGE_PRIV, + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; -/// Builtin IDM Group for granting elevated people (personal data) write permissions. -pub const JSON_IDM_PEOPLE_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_people_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000003"], - "description": ["Builtin IDM Group for granting elevated people (personal data) write permissions."], - "member": [ - "00000000-0000-0000-0000-000000000013", - "00000000-0000-0000-0000-000000000024" - ] - } -}"#; + /// Builtin IDM Group for importing passwords to person accounts - intended for service account membership only. + pub static ref IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_people_account_password_import_priv", + description: "Builtin IDM Group for importing passwords to person accounts - intended for service account membership only.", + uuid: UUID_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV, + members: vec![UUID_IDM_ADMINS], + ..Default::default() + }; -/// Builtin IDM Group for importing passwords to person accounts - intended for service account membership only. -pub const JSON_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_people_account_password_import_priv"], - "uuid": ["00000000-0000-0000-0000-000000000023"], - "description": ["Builtin IDM Group for importing passwords to person accounts - intended for service account membership only."] - } -}"#; + /// Builtin IDM Group for allowing the ability to extend accounts to have the "person" flag set. + pub static ref IDM_PEOPLE_EXTEND_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_people_extend_priv", + description: "Builtin System Administrators Group.", + uuid: UUID_IDM_PEOPLE_EXTEND_PRIV, + members: vec![BUILTIN_ACCOUNT_ADMIN.uuid], + ..Default::default() + }; + /// Self-write of mail + pub static ref IDM_PEOPLE_SELF_WRITE_MAIL_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_people_self_write_mail_priv", + description: "Builtin IDM Group for people accounts to update their own mail.", + uuid: UUID_IDM_PEOPLE_SELF_WRITE_MAIL_PRIV, + members: Vec::new(), + ..Default::default() + }; -/// Builtin IDM Group for allowing the ability to extend accounts to have the "person" flag set. -pub const JSON_IDM_PEOPLE_EXTEND_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_people_extend_priv"], - "uuid": ["00000000-0000-0000-0000-000000000024"], - "description": ["Builtin IDM Group for extending accounts to be people."], - "member": [ - "00000000-0000-0000-0000-000000000001" - ] - } -}"#; + /// Builtin IDM Group for granting elevated high privilege people (personal data) read permissions. + pub static ref IDM_HP_PEOPLE_READ_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_people_read_priv", + description: "Builtin IDM Group for granting elevated high privilege people (personal data) read permissions.", + uuid: UUID_IDM_HP_PEOPLE_READ_PRIV, + members: vec![UUID_IDM_HP_PEOPLE_WRITE_PRIV], + ..Default::default() + }; -// Self-write of mail -pub const JSON_IDM_PEOPLE_SELF_WRITE_MAIL_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_people_self_write_mail_priv"], - "uuid": ["00000000-0000-0000-0000-000000000033"], - "description": ["Builtin IDM Group for people accounts to update their own mail."] - } -}"#; + /// Builtin IDM Group for granting elevated high privilege people (personal data) write permissions. + pub static ref IDM_HP_PEOPLE_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_people_write_priv", + description: "Builtin IDM Group for granting elevated high privilege people (personal data) write permissions.", + uuid: UUID_IDM_HP_PEOPLE_WRITE_PRIV, + members: vec![UUID_IDM_HP_PEOPLE_EXTEND_PRIV], + ..Default::default() + }; -/// Builtin IDM Group for granting elevated high privilege people (personal data) read permissions. -pub const JSON_IDM_HP_PEOPLE_READ_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_people_read_priv"], - "uuid": ["00000000-0000-0000-0000-000000000028"], - "description": ["Builtin IDM Group for granting elevated high privilege people (personal data) read permissions."], - "member": ["00000000-0000-0000-0000-000000000029"] - } -}"#; - -/// Builtin IDM Group for granting elevated high privilege people (personal data) write permissions. -pub const JSON_IDM_HP_PEOPLE_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_people_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000029"], - "description": ["Builtin IDM Group for granting elevated high privilege people (personal data) write permissions."], - "member": [ - "00000000-0000-0000-0000-000000000030" - ] - } -}"#; - -/// Builtin IDM Group for extending high privilege accounts to be people. -pub const JSON_IDM_HP_PEOPLE_EXTEND_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_people_extend_priv"], - "uuid": ["00000000-0000-0000-0000-000000000030"], - "description": ["Builtin IDM Group for extending high privilege accounts to be people."], - "member": [ - "00000000-0000-0000-0000-000000000000" - ] - } -}"#; + /// Builtin IDM Group for extending high privilege accounts to be people. + pub static ref IDM_HP_PEOPLE_EXTEND_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_people_extend_priv", + description: "Builtin IDM Group for extending high privilege accounts to be people.", + uuid: UUID_IDM_HP_PEOPLE_EXTEND_PRIV, + members: vec![BUILTIN_ACCOUNT_ADMIN.uuid], + ..Default::default() + }; // * group write manager (no read, everyone has read via the anon, etc) -// IDM_GROUP_CREATE_PRIV -/// Builtin IDM Group for granting elevated group write and lifecycle permissions. -pub const JSON_IDM_GROUP_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_group_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000015"], - "description": ["Builtin IDM Group for granting elevated group write and lifecycle permissions."], - "member": [ - "00000000-0000-0000-0000-000000000001", - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; -pub const JSON_IDM_GROUP_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_group_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000004"], - "description": ["Builtin IDM Group for granting elevated group write permissions."], - "member": [ - "00000000-0000-0000-0000-000000000015" - ] - } -}"#; -pub const JSON_IDM_GROUP_UNIX_EXTEND_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_group_unix_extend_priv"], - "uuid": ["00000000-0000-0000-0000-000000000022"], - "description": ["Builtin IDM Group for granting unix group extension permissions."], - "member": [ - "00000000-0000-0000-0000-000000000001" - ] - } -}"#; -// * account read manager -pub const JSON_IDM_ACCOUNT_READ_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_account_read_priv"], - "uuid": ["00000000-0000-0000-0000-000000000005"], - "description": ["Builtin IDM Group for granting elevated account read permissions."], - "member": [ - "00000000-0000-0000-0000-000000000006" - ] - } -}"#; -// * account write manager -pub const JSON_IDM_ACCOUNT_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_account_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000014"], - "description": ["Builtin IDM Group for granting elevated account write and lifecycle permissions."], - "member": [ - "00000000-0000-0000-0000-000000000001" - ] - } -}"#; -pub const JSON_IDM_ACCOUNT_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_account_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000006"], - "description": ["Builtin IDM Group for granting elevated account write permissions."], - "member": ["00000000-0000-0000-0000-000000000014"] - } -}"#; -pub const JSON_IDM_ACCOUNT_UNIX_EXTEND_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_account_unix_extend_priv"], - "uuid": ["00000000-0000-0000-0000-000000000021"], - "description": ["Builtin IDM Group for granting account unix extend permissions."], - "member": ["00000000-0000-0000-0000-000000000001"] - } -}"#; -// * RADIUS servers -/// Builtin IDM Group for RADIUS secret write for all non-hp accounts. -pub const JSON_IDM_RADIUS_SECRET_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_radius_secret_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000031"], - "description": ["Builtin IDM Group for RADIUS secret write for all non-hp accounts."], - "member": ["00000000-0000-0000-0000-000000000001"] - } -}"#; + /// Builtin IDM Group for granting elevated group write and lifecycle permissions. + pub static ref IDM_GROUP_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_group_manage_priv", + description: "Builtin IDM Group for granting elevated group write and lifecycle permissions.", + uuid: UUID_IDM_GROUP_MANAGE_PRIV, + members: vec![ + BUILTIN_GROUP_IDM_ADMINS_V1.uuid, + BUILTIN_GROUP_SYSTEM_ADMINS_V1.uuid, + ], + ..Default::default() + }; -/// Builtin IDM Group for RADIUS secret reading for all non-hp accounts. -pub const JSON_IDM_RADIUS_SECRET_READ_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_radius_secret_read_priv"], - "uuid": ["00000000-0000-0000-0000-000000000032"], - "description": ["Builtin IDM Group for RADIUS secret reading for all non-hp accounts."], - "member": ["00000000-0000-0000-0000-000000000031"] - } -}"#; + /// Builtin IDM Group for granting elevated group write and lifecycle permissions. + pub static ref IDM_GROUP_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_group_write_priv", + description: "Builtin IDM Group for granting elevated group write permissions.", + uuid: UUID_IDM_GROUP_WRITE_PRIV, + members: vec![ + UUID_IDM_GROUP_MANAGE_PRIV + ], + ..Default::default() + }; -/// Builtin IDM Group for RADIUS server access delegation. -pub const JSON_IDM_RADIUS_SERVERS_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_radius_servers"], - "uuid": ["00000000-0000-0000-0000-000000000007"], - "description": ["Builtin IDM Group for RADIUS server access delegation."] - } -}"#; + /// Builtin IDM Group for granting unix group extension permissions. + pub static ref IDM_GROUP_UNIX_EXTEND_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_group_unix_extend_priv", + description: "Builtin IDM Group for granting UNIX group extension permissions.", + uuid: UUID_IDM_GROUP_UNIX_EXTEND_PRIV, + members: vec![ + UUID_IDM_ADMINS + ], + ..Default::default() + }; -// * high priv account read manager -pub const JSON_IDM_HP_ACCOUNT_READ_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_account_read_priv"], - "uuid": ["00000000-0000-0000-0000-000000000008"], - "description": ["Builtin IDM Group for granting elevated account read permissions over high privilege accounts."], - "member": [ - "00000000-0000-0000-0000-000000000009" - ] - } -}"#; + /// Account read manager + pub static ref IDM_ACCOUNT_READ_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_account_read_priv", + description: "Builtin IDM Group for granting elevated account read permissions.", + uuid: UUID_IDM_ACCOUNT_READ_PRIV, + members: vec![ + UUID_IDM_ACCOUNT_WRITE_PRIV, + ], + ..Default::default() + }; -// * high priv account write manager -pub const JSON_IDM_HP_ACCOUNT_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_account_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000016"], - "description": ["Builtin IDM Group for granting elevated account write and lifecycle permissions over high privilege accounts."], - "member": [ - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; + pub static ref IDM_ACCOUNT_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_account_manage_priv", + description: "Builtin IDM Group for granting elevated account write and lifecycle permissions.", + uuid: UUID_IDM_ACCOUNT_MANAGE_PRIV, + members: vec![ + UUID_IDM_ADMINS, + ], + ..Default::default() + }; -/// Builtin IDM Group for granting elevated account write permissions over high privilege accounts. -pub const JSON_IDM_HP_ACCOUNT_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_account_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000009"], - "description": ["Builtin IDM Group for granting elevated account write permissions over high privilege accounts."], - "member": [ - "00000000-0000-0000-0000-000000000016" - ] - } -}"#; + pub static ref IDM_ACCOUNT_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_account_write_priv", + description: "Builtin IDM Group for granting elevated account write permissions.", + uuid: UUID_IDM_ACCOUNT_WRITE_PRIV, + members: vec![ + UUID_IDM_ACCOUNT_MANAGE_PRIV, + ], + ..Default::default() + }; -/// Builtin IDM Group for granting account unix extend permissions for high privilege accounts. -pub const JSON_IDM_HP_ACCOUNT_UNIX_EXTEND_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_account_unix_extend_priv"], - "uuid": ["00000000-0000-0000-0000-000000000025"], - "description": ["Builtin IDM Group for granting account unix extend permissions for high privilege accounts."], - "member": ["00000000-0000-0000-0000-000000000019"] - } -}"#; + pub static ref IDM_ACCOUNT_UNIX_EXTEND_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_account_unix_extend_priv", + description: "Builtin IDM Group for granting account unix extend permissions.", + uuid: UUID_IDM_ACCOUNT_UNIX_EXTEND_PRIV, + members: vec![ + UUID_IDM_ADMINS, + ], + ..Default::default() + }; -// * Schema write manager -pub const JSON_IDM_SCHEMA_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_schema_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000010"], - "description": ["Builtin IDM Group for granting elevated schema write and management permissions."], - "member": [ - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; + /// Builtin IDM Group for RADIUS secret write for all non-hp accounts. + pub static ref IDM_RADIUS_SECRET_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_radius_secret_write_priv", + description: "Builtin IDM Group for RADIUS secret write for all non-hp accounts.", + uuid: UUID_IDM_RADIUS_SECRET_WRITE_PRIV_V1, + members: vec![ + UUID_IDM_ADMINS, + ], + ..Default::default() + }; -// * ACP read/write manager -pub const JSON_IDM_ACP_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_acp_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000011"], - "description": ["Builtin IDM Group for granting control over all access control profile modifications."], - "member": ["00000000-0000-0000-0000-000000000019"] - } -}"#; + /// Builtin IDM Group for RADIUS secret reading for all non-hp accounts. + pub static ref IDM_RADIUS_SECRET_READ_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_radius_secret_read_priv", + description: "Builtin IDM Group for RADIUS secret reading for all non-hp accounts.", + uuid: UUID_IDM_RADIUS_SECRET_READ_PRIV_V1, + members: vec![ + UUID_IDM_RADIUS_SECRET_WRITE_PRIV_V1, + ], + ..Default::default() + }; -// Builtin IDM Group for granting elevated group write and lifecycle privileges for high privilege groups. -pub const JSON_IDM_HP_GROUP_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_group_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000017"], - "description": ["Builtin IDM Group for granting elevated group write and lifecycle privileges for high privilege groups."], - "member": ["00000000-0000-0000-0000-000000000019"] - } -}"#; + /// Builtin IDM Group for RADIUS server access delegation. + pub static ref IDM_RADIUS_SERVERS_V1: BuiltinGroup = BuiltinGroup { + name: "idm_radius_servers", + description: "Builtin IDM Group for RADIUS server access delegation.", + uuid: UUID_IDM_RADIUS_SERVERS, + members: vec![ + ], + ..Default::default() + }; -/// Builtin IDM Group for granting elevated group write privileges for high privilege groups. -pub const JSON_IDM_HP_GROUP_WRITE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_group_write_priv"], - "uuid": ["00000000-0000-0000-0000-000000000012"], - "description": ["Builtin IDM Group for granting elevated group write privileges for high privilege groups."], - "member": [ - "00000000-0000-0000-0000-000000000017" - ] - } -}"#; + /// High privilege account read manager + pub static ref IDM_HP_ACCOUNT_READ_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_account_read_priv", + description: "Builtin IDM Group for granting elevated account read permissions over high privilege accounts.", + uuid: UUID_IDM_HP_ACCOUNT_READ_PRIV, + members: vec![ + UUID_IDM_HP_ACCOUNT_WRITE_PRIV + ], + ..Default::default() + }; -/// Builtin IDM Group for granting unix group extension permissions for high privilege groups. -pub const JSON_IDM_HP_GROUP_UNIX_EXTEND_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_group_unix_extend_priv"], - "uuid": ["00000000-0000-0000-0000-000000000026"], - "description": ["Builtin IDM Group for granting unix group extension permissions for high privilege groups."], - "member": [ - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; + /// Builtin IDM Group for granting elevated account write permissions over high privilege accounts. + pub static ref IDM_HP_ACCOUNT_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_account_manage_priv", + description: "Builtin IDM Group for granting elevated account write and lifecycle permissions over high privilege accounts.", + uuid: UUID_IDM_HP_ACCOUNT_MANAGE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; + /// Builtin IDM Group for granting elevated account write permissions over high privilege accounts. + pub static ref IDM_HP_ACCOUNT_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_account_write_priv", + description: "Builtin IDM Group for granting elevated account write permissions over high privilege accounts.", + uuid: UUID_IDM_HP_ACCOUNT_WRITE_PRIV, + members: vec![ + UUID_IDM_HP_ACCOUNT_MANAGE_PRIV, + ], + ..Default::default() + }; -/// Builtin IDM Group for granting local domain administration rights and trust administration rights -pub const JSON_DOMAIN_ADMINS: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["domain_admins"], - "uuid": ["00000000-0000-0000-0000-000000000020"], - "description": ["Builtin IDM Group for granting local domain administration rights and trust administration rights."], - "member": [ - "00000000-0000-0000-0000-000000000000" - ] - } -}"#; + /// Builtin IDM Group for granting account unix extend permissions for high privilege accounts. + pub static ref IDM_HP_ACCOUNT_UNIX_EXTEND_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_account_unix_extend_priv", + description: "Builtin IDM Group for granting account UNIX extend permissions for high privilege accounts.", + uuid: UUID_IDM_HP_ACCOUNT_UNIX_EXTEND_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; -pub const JSON_IDM_HP_OAUTH2_MANAGE_PRIV_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_oauth2_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000027"], - "description": ["Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain."], - "member": [ - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; + /// * Schema write manager + pub static ref IDM_SCHEMA_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_schema_manage_priv", + description: "Builtin IDM Group for granting elevated schema write and management permissions.", + uuid: UUID_IDM_SCHEMA_MANAGE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; -pub const JSON_IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_service_account_into_person_migrate_priv"], - "uuid": ["00000000-0000-0000-0000-000000000034"], - "description": ["Builtin IDM Group for allowing migrations of service accounts into persons"], - "member": [ - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; + /// ACP read/write manager + pub static ref IDM_ACP_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_acp_manage_priv", + description: "Builtin IDM Group for granting control over all access control profile modifications.", + uuid: UUID_IDM_ACP_MANAGE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; -/// Builtin System Admin account. -pub const JSON_IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_hp_sync_account_manage_priv"], - "uuid": ["00000000-0000-0000-0000-000000000037"], - "description": ["Builtin IDM Group for managing synchronisation from external identity sources"], - "member": [ - "00000000-0000-0000-0000-000000000019" - ] - } -}"#; + /// Builtin IDM Group for granting elevated group write and lifecycle privileges for high privilege groups. + pub static ref IDM_HP_GROUP_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_group_manage_priv", + description: "Builtin IDM Group for granting elevated group write and lifecycle privileges for high privilege groups.", + uuid: UUID_IDM_HP_GROUP_MANAGE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; -// == dyn groups + /// Builtin IDM Group for granting elevated group write privileges for high privilege groups. + pub static ref IDM_HP_GROUP_WRITE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_group_write_priv", + description: "Builtin IDM Group for granting elevated group write privileges for high privilege groups.", + uuid: UUID_IDM_HP_GROUP_WRITE_PRIV, + members: vec![ + UUID_IDM_HP_GROUP_MANAGE_PRIV, + ], + ..Default::default() + }; -pub const JSON_IDM_ALL_PERSONS: &str = r#"{ - "attrs": { - "class": ["dyngroup", "group", "object"], - "name": ["idm_all_persons"], - "uuid": ["00000000-0000-0000-0000-000000000035"], - "description": ["Builtin IDM dynamic group containing all persons that can authenticate"], - "dyngroup_filter": [ - "{\"and\": [{\"eq\": [\"class\",\"person\"]}, {\"eq\": [\"class\",\"account\"]}]}" - ] - } -}"#; - -pub const JSON_IDM_ALL_ACCOUNTS: &str = r#"{ - "attrs": { - "class": ["dyngroup", "group", "object"], - "name": ["idm_all_accounts"], - "uuid": ["00000000-0000-0000-0000-000000000036"], - "description": ["Builtin IDM dynamic group containing all entries that can authenticate."], - "dyngroup_filter": [ - "{\"eq\":[\"class\",\"account\"]}" - ] - } -}"#; - -lazy_static! { - pub static ref E_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES: EntryInitNew = entry_init!( - (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - (Attribute::Class.as_ref(), EntryClass::Group.to_value()), - ( - Attribute::Name.as_ref(), - Value::new_iname("idm_ui_enable_experimental_features") - ), - ( - Attribute::Uuid.as_ref(), - Value::Uuid(UUID_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES) - ), - ( - Attribute::Description.as_ref(), - Value::new_utf8s( - "Members of this group will have access to experimental web UI features." - ) - ), - (Attribute::GrantUiHint.as_ref(), Value::UiHint(UiHint::ExperimentalFeatures)) - ); - - pub static ref E_IDM_ACCOUNT_MAIL_READ_PRIV: EntryInitNew = entry_init!( - (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - (Attribute::Class.as_ref(), EntryClass::Group.to_value()), - ( - Attribute::Name.as_ref(), - Value::new_iname("idm_account_mail_read_priv") - ), - ( - Attribute::Uuid.as_ref(), - Value::Uuid(UUID_IDM_ACCOUNT_MAIL_READ_PRIV) - ), - ( - Attribute::Description.as_ref(), - Value::new_utf8s( - "Members of this group will have access to read the mail attribute of all persons and service accounts." - ) - ) - ); } - -/// This must be the last group to init to include the UUID of the other high priv groups. -pub const JSON_IDM_HIGH_PRIVILEGE_V1: &str = r#"{ - "attrs": { - "class": ["group", "object"], - "name": ["idm_high_privilege"], - "uuid": ["00000000-0000-0000-0000-000000001000"], - "description": ["Builtin IDM provided groups with high levels of access that should be audited and limited in modification."], - "member": [ - "00000000-0000-0000-0000-000000000001", - "00000000-0000-0000-0000-000000000002", - "00000000-0000-0000-0000-000000000003", - "00000000-0000-0000-0000-000000000004", - "00000000-0000-0000-0000-000000000005", - "00000000-0000-0000-0000-000000000006", - "00000000-0000-0000-0000-000000000007", - "00000000-0000-0000-0000-000000000008", - "00000000-0000-0000-0000-000000000009", - "00000000-0000-0000-0000-000000000010", - "00000000-0000-0000-0000-000000000011", - "00000000-0000-0000-0000-000000000012", - "00000000-0000-0000-0000-000000000013", - "00000000-0000-0000-0000-000000000014", - "00000000-0000-0000-0000-000000000015", - "00000000-0000-0000-0000-000000000016", - "00000000-0000-0000-0000-000000000017", - "00000000-0000-0000-0000-000000000019", - "00000000-0000-0000-0000-000000000020", - "00000000-0000-0000-0000-000000000023", - "00000000-0000-0000-0000-000000000024", - "00000000-0000-0000-0000-000000000025", - "00000000-0000-0000-0000-000000000026", - "00000000-0000-0000-0000-000000000027", - "00000000-0000-0000-0000-000000000031", - "00000000-0000-0000-0000-000000000032", - "00000000-0000-0000-0000-000000000034", - "00000000-0000-0000-0000-000000000037", - "00000000-0000-0000-0000-000000001000" - ] - } -}"#; - +// at some point vs code just gives up on syntax highlighting inside lazy_static... lazy_static! { + + /// Builtin IDM Group for granting unix group extension permissions for high privilege groups. + pub static ref IDM_HP_GROUP_UNIX_EXTEND_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_group_unix_extend_priv", + description: "Builtin IDM Group for granting unix group extension permissions for high privilege groups.", + uuid: UUID_IDM_HP_GROUP_UNIX_EXTEND_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; + + /// Builtin IDM Group for granting local domain administration rights and trust administration rights + pub static ref 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, + members: vec![ + UUID_ADMIN, + ], + ..Default::default() + }; + + + /// Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain. + pub static ref IDM_HP_OAUTH2_MANAGE_PRIV_V1: BuiltinGroup = BuiltinGroup { + name: "idm_hp_oauth2_manage_priv", + description: "Builtin IDM Group for managing oauth2 resource server integrations to this authentication domain.", + uuid: UUID_IDM_HP_OAUTH2_MANAGE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; + + /// Builtin IDM Group for allowing migrations of service accounts into persons + pub static ref IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV: BuiltinGroup = BuiltinGroup { + name: "idm_hp_service_account_into_person_migrate_priv", + description:"Builtin IDM Group for allowing migrations of service accounts into persons", + uuid: UUID_IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; + + + /// Builtin IDM Group for allowing migrations of service accounts into persons + pub static ref IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV: BuiltinGroup = BuiltinGroup { + name: "idm_hp_sync_account_manage_priv", + description: "Builtin IDM Group for managing synchronisation from external identity sources", + uuid: UUID_IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV, + members: vec![ + UUID_SYSTEM_ADMINS, + ], + ..Default::default() + }; + + /// Builtin IDM Group for extending high privilege accounts to be people. + pub static ref IDM_ALL_PERSONS: BuiltinGroup = BuiltinGroup { + name: "idm_all_persons", + description: "Builtin IDM Group for extending high privilege accounts to be people.", + uuid: UUID_IDM_ALL_PERSONS, + members: Vec::new(), + 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()), + ]) + ), + ..Default::default() + }; + + /// Builtin IDM Group for extending high privilege accounts to be people. + 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::new(), + dyngroup: true, + dyngroup_filter: Some( + Filter::Eq(Attribute::Class.to_string(), EntryClass::Account.to_string()), + ), + ..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, + 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_PRIV: BuiltinGroup = BuiltinGroup { + name: "idm_account_mail_read_priv", + description: "Members of this group will have access to read the mail attribute of all persons and service accounts.", + uuid: UUID_IDM_ACCOUNT_MAIL_READ_PRIV, + ..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_V1: BuiltinGroup = BuiltinGroup { + name: "idm_high_privilege", + uuid: UUID_IDM_HIGH_PRIVILEGE, + description: "Builtin IDM provided groups with high levels of access that should be audited and limited in modification.", + members: vec![ + UUID_IDM_ADMINS, + UUID_IDM_PEOPLE_READ_PRIV, + UUID_IDM_PEOPLE_WRITE_PRIV, + UUID_IDM_GROUP_WRITE_PRIV, + UUID_IDM_ACCOUNT_READ_PRIV, + UUID_IDM_ACCOUNT_WRITE_PRIV, + UUID_IDM_RADIUS_SERVERS, + UUID_IDM_HP_ACCOUNT_READ_PRIV, + UUID_IDM_HP_ACCOUNT_WRITE_PRIV, + UUID_IDM_SCHEMA_MANAGE_PRIV, + UUID_IDM_ACP_MANAGE_PRIV, + UUID_IDM_HP_GROUP_WRITE_PRIV, + UUID_IDM_PEOPLE_MANAGE_PRIV, + UUID_IDM_ACCOUNT_MANAGE_PRIV, + UUID_IDM_GROUP_MANAGE_PRIV, + UUID_IDM_HP_ACCOUNT_MANAGE_PRIV, + UUID_IDM_HP_GROUP_MANAGE_PRIV, + UUID_SYSTEM_ADMINS, + UUID_DOMAIN_ADMINS, + UUID_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV, + UUID_IDM_PEOPLE_EXTEND_PRIV, + UUID_IDM_HP_ACCOUNT_UNIX_EXTEND_PRIV, + UUID_IDM_HP_GROUP_UNIX_EXTEND_PRIV, + UUID_IDM_HP_OAUTH2_MANAGE_PRIV, + UUID_IDM_RADIUS_SECRET_WRITE_PRIV_V1, + UUID_IDM_RADIUS_SECRET_READ_PRIV_V1, + UUID_IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV, + UUID_IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV, + UUID_IDM_HIGH_PRIVILEGE, + ], + dyngroup: false, + dyngroup_filter: None, + extra_attributes: Vec::new(), + }; + pub static ref E_SYSTEM_INFO_V1: EntryInitNew = entry_init!( (Attribute::Class.as_ref(), EntryClass::Object.to_value()), (Attribute::Class.as_ref(), EntryClass::SystemInfo.to_value()), @@ -1270,9 +1179,7 @@ lazy_static! { ), (Attribute::Version.as_ref(), Value::Uint32(14)) ); -} -lazy_static! { pub static ref E_DOMAIN_INFO_V1: EntryInitNew = entry_init!( (Attribute::Class.as_ref(), EntryClass::Object.to_value()), (Attribute::Class.as_ref(), EntryClass::DomainInfo.to_value()), @@ -1286,20 +1193,10 @@ lazy_static! { ); } -// Anonymous should be the last object in the range here. -// pub const JSON_ANONYMOUS_V1: &str = r#"{ -// "attrs": { -// "class": ["account", "service_account", "object"], -// "name": ["anonymous"], -// "uuid": ["00000000-0000-0000-0000-ffffffffffff"], -// "description": ["Anonymous access account."], -// "displayname": ["Anonymous"] -// } -// }"#; - #[derive(Debug, Clone)] /// Built in accounts such as anonymous, idm_admin and admin pub struct BuiltinAccount { + // TODO: this really should be a "are you a service account or a person" enum pub classes: Vec, pub name: &'static str, pub uuid: Uuid, @@ -1319,6 +1216,20 @@ impl Default for BuiltinAccount { } } +impl From for Account { + fn from(value: BuiltinAccount) -> Self { + 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::new(), + ..Default::default() + } + } +} + impl From for EntryInitNew { fn from(value: BuiltinAccount) -> Self { let mut entry = EntryInitNew::new(); @@ -1349,36 +1260,32 @@ impl From for EntryInitNew { } lazy_static! { - // pub static ref E_ANONYMOUS_V1: EntryInitNew = entry_init!( - // (Attribute::Class.as_ref(), EntryClass::Object.to_value()), - // (Attribute::Class.as_ref(), EntryClass::Account.to_value()), - // ( - // Attribute::Class.as_ref(), - // EntryClass::ServiceAccount.to_value() - // ), - // (Attribute::Name.as_ref(), Value::new_iname("anonymous")), - // (Attribute::Uuid.as_ref(), Value::Uuid(UUID_ANONYMOUS)), - // ( - // Attribute::Description.as_ref(), - // Value::new_utf8s("Anonymous access account.") - // ), - // ( - // Attribute::DisplayName.as_ref(), - // Value::new_utf8s("Anonymous") - // ) - // ); - pub static ref ACCOUNT_ANONYMOUS_V1: BuiltinAccount = BuiltinAccount { + + /// Builtin System Admin account. + pub static ref BUILTIN_ACCOUNT_ADMIN: BuiltinAccount = BuiltinAccount { + classes: vec![ + EntryClass::Account, + EntryClass::ServiceAccount, + EntryClass::MemberOf, + EntryClass::Object, + ], + name: "admin", + uuid: UUID_ADMIN, + description: "Builtin System Admin account.", + displayname: "System Administrator", + }; + pub static ref BUILTIN_ACCOUNT_ANONYMOUS_V1: BuiltinAccount = BuiltinAccount { classes: [ EntryClass::Account, EntryClass::ServiceAccount, EntryClass::Object, - ].to_vec(), + ] + .to_vec(), name: "anonymous", uuid: UUID_ANONYMOUS, description: "Anonymous access account.", displayname: "Anonymous", }; - pub static ref E_ANONYMOUS_V1: EntryInitNew = ACCOUNT_ANONYMOUS_V1.clone().into(); } // ============ TEST DATA ============ diff --git a/server/lib/src/event.rs b/server/lib/src/event.rs index ee8b0d6af..1ab835e8a 100644 --- a/server/lib/src/event.rs +++ b/server/lib/src/event.rs @@ -666,11 +666,11 @@ impl ModifyEvent { /// This is a TEST ONLY method and will never be exposed in production. #[cfg(test)] pub fn new_impersonate_entry_ser( - e: &str, + e: BuiltinAccount, filter: Filter, modlist: ModifyList, ) -> Self { - let ei: Entry = Entry::unsafe_from_entry_str(e); + let ei: EntryInitNew = e.into(); ModifyEvent { ident: Identity::from_impersonate_entry_readwrite(Arc::new(ei.into_sealed_committed())), filter: filter.clone().into_valid(), diff --git a/server/lib/src/idm/account.rs b/server/lib/src/idm/account.rs index 4dd4d3b5c..8d4fdcdec 100644 --- a/server/lib/src/idm/account.rs +++ b/server/lib/src/idm/account.rs @@ -146,7 +146,7 @@ macro_rules! try_from_entry { }}; } -#[derive(Debug, Clone)] +#[derive(Default, Debug, Clone)] pub struct Account { // Later these could be &str if we cache entry here too ... // They can't because if we mod the entry, we'll lose the ref. @@ -807,13 +807,14 @@ impl<'a> IdmServerProxyReadTransaction<'a> { #[cfg(test)] mod tests { + use crate::idm::account::Account; use crate::prelude::*; use kanidm_proto::v1::UiHint; #[test] fn test_idm_account_from_anonymous() { - let anon_e = entry_to_account!(E_ANONYMOUS_V1.clone()); - debug!("{:?}", anon_e); + let account: Account = BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into(); + debug!("{:?}", account); // I think that's it? we may want to check anonymous mech ... } diff --git a/server/lib/src/idm/authsession.rs b/server/lib/src/idm/authsession.rs index 188493024..c1d8aa175 100644 --- a/server/lib/src/idm/authsession.rs +++ b/server/lib/src/idm/authsession.rs @@ -1251,6 +1251,7 @@ mod tests { use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP}; use crate::credential::{BackupCodes, Credential}; + use crate::idm::account::Account; use crate::idm::audit::AuditEvent; use crate::idm::authsession::{ AuthSession, BAD_AUTH_TYPE_MSG, BAD_BACKUPCODE_MSG, BAD_PASSWORD_MSG, BAD_TOTP_MSG, @@ -1288,7 +1289,7 @@ mod tests { let webauthn = create_webauthn(); - let anon_account = entry_to_account!(E_ANONYMOUS_V1.clone()); + let anon_account: Account = BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into(); let (session, state) = AuthSession::new( anon_account, @@ -1361,7 +1362,7 @@ mod tests { fn start_session_simple_password_mech(privileged: bool) -> UserAuthToken { let webauthn = create_webauthn(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1.clone()); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); // manually load in a cred let p = CryptoPolicy::minimum(); let cred = Credential::new_password_only(&p, "test_password").unwrap(); @@ -1463,7 +1464,7 @@ mod tests { let jws_signer = create_jwt_signer(); let webauthn = create_webauthn(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1.clone()); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); // manually load in a cred let p = CryptoPolicy::minimum(); let cred = Credential::new_password_only(&p, "list@no3IBTyqHu$bad").unwrap(); @@ -1566,7 +1567,7 @@ mod tests { let webauthn = create_webauthn(); let jws_signer = create_jwt_signer(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); @@ -1756,7 +1757,7 @@ mod tests { let webauthn = create_webauthn(); let jws_signer = create_jwt_signer(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); @@ -1933,7 +1934,7 @@ mod tests { let (audit_tx, mut audit_rx) = unbounded(); let ts = duration_from_epoch_now(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1.clone()); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); let (webauthn, mut wa, wan_cred) = setup_webauthn_passkey(account.name.as_str()); let jws_signer = create_jwt_signer(); @@ -2092,7 +2093,7 @@ mod tests { let (audit_tx, mut audit_rx) = unbounded(); let ts = duration_from_epoch_now(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); let (webauthn, mut wa, wan_cred) = setup_webauthn_securitykey(account.name.as_str()); let jws_signer = create_jwt_signer(); @@ -2299,7 +2300,7 @@ mod tests { let (audit_tx, mut audit_rx) = unbounded(); let ts = duration_from_epoch_now(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); let (webauthn, mut wa, wan_cred) = setup_webauthn_securitykey(account.name.as_str()); let jws_signer = create_jwt_signer(); @@ -2586,7 +2587,7 @@ mod tests { let jws_signer = create_jwt_signer(); let webauthn = create_webauthn(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); @@ -2809,7 +2810,7 @@ mod tests { let webauthn = create_webauthn(); let jws_signer = create_jwt_signer(); // create the ent - let mut account = entry_to_account!(E_ADMIN_V1); + let mut account: Account = BUILTIN_ACCOUNT_ADMIN.clone().into(); // Setup a fake time stamp for consistency. let ts = Duration::from_secs(12345); diff --git a/server/lib/src/macros.rs b/server/lib/src/macros.rs index 54e13ee37..801435758 100644 --- a/server/lib/src/macros.rs +++ b/server/lib/src/macros.rs @@ -60,29 +60,6 @@ macro_rules! setup_test { }}; } -#[cfg(test)] -macro_rules! entry_to_account { - ($entry:expr) => {{ - use std::iter::once; - - use crate::entry::{Entry, EntryInvalid, EntryNew}; - use crate::idm::account::Account; - use crate::value::Value; - - let mut e: Entry = $entry.clone().into_invalid_new(); - // Add spn, because normally this is generated but in tests we can't. - let spn = e - .get_ava_single_iname(Attribute::Name.as_ref()) - .map(|s| Value::new_spn_str(s, "example.com")) - .expect("Failed to munge spn from name!"); - e.set_ava(Attribute::Spn.as_ref(), once(spn)); - - let e = e.into_sealed_committed(); - - Account::try_from_entry_no_groups(&e).expect("Account conversion failure") - }}; -} - // Test helpers for all plugins. // #[macro_export] #[cfg(test)] diff --git a/server/lib/src/repl/tests.rs b/server/lib/src/repl/tests.rs index d47c07813..7bbef4155 100644 --- a/server/lib/src/repl/tests.rs +++ b/server/lib/src/repl/tests.rs @@ -1846,7 +1846,7 @@ async fn test_repl_increment_consumer_lagging_attributes( drop(server_b_txn); } -// Test two synchronised nodes where no changes occured in a TS/RUV window. +// Test two synchronised nodes where no changes occurred in a TS/RUV window. #[qs_pair_test] async fn test_repl_increment_consumer_ruv_trim_past_valid( server_a: &QueryServer, diff --git a/server/lib/src/server/migrations.rs b/server/lib/src/server/migrations.rs index b84b2db17..ce559488e 100644 --- a/server/lib/src/server/migrations.rs +++ b/server/lib/src/server/migrations.rs @@ -603,12 +603,12 @@ impl<'a> QueryServerWriteTransaction<'a> { // Check the admin object exists (migrations). // Create the default idm_admin group. - let admin_entries = [ - E_ANONYMOUS_V1.clone(), - E_ADMIN_V1.clone(), - E_IDM_ADMIN_V1.clone(), - E_IDM_ADMINS_V1.clone(), - E_SYSTEM_ADMINS_V1.clone(), + let admin_entries: Vec = vec![ + BUILTIN_ACCOUNT_ANONYMOUS_V1.clone().into(), + BUILTIN_ACCOUNT_ADMIN.clone().into(), + BUILTIN_ACCOUNT_IDM_ADMIN.clone().into(), + BUILTIN_GROUP_IDM_ADMINS_V1.clone().try_into()?, + BUILTIN_GROUP_SYSTEM_ADMINS_V1.clone().try_into()?, ]; let res: Result<(), _> = admin_entries .into_iter() @@ -621,53 +621,52 @@ impl<'a> QueryServerWriteTransaction<'a> { res?; // Create any system default schema entries. - - // Create any system default access profile entries. - let idm_entries = [ - // Builtin dyn groups, - JSON_IDM_ALL_PERSONS, - JSON_IDM_ALL_ACCOUNTS, - // Builtin groups - JSON_IDM_PEOPLE_MANAGE_PRIV_V1, - JSON_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1, - JSON_IDM_PEOPLE_EXTEND_PRIV_V1, - JSON_IDM_PEOPLE_SELF_WRITE_MAIL_PRIV_V1, - JSON_IDM_PEOPLE_WRITE_PRIV_V1, - JSON_IDM_PEOPLE_READ_PRIV_V1, - JSON_IDM_HP_PEOPLE_EXTEND_PRIV_V1, - JSON_IDM_HP_PEOPLE_WRITE_PRIV_V1, - JSON_IDM_HP_PEOPLE_READ_PRIV_V1, - JSON_IDM_GROUP_MANAGE_PRIV_V1, - JSON_IDM_GROUP_WRITE_PRIV_V1, - JSON_IDM_GROUP_UNIX_EXTEND_PRIV_V1, - JSON_IDM_ACCOUNT_MANAGE_PRIV_V1, - JSON_IDM_ACCOUNT_WRITE_PRIV_V1, - JSON_IDM_ACCOUNT_UNIX_EXTEND_PRIV_V1, - JSON_IDM_ACCOUNT_READ_PRIV_V1, - JSON_IDM_RADIUS_SECRET_WRITE_PRIV_V1, - JSON_IDM_RADIUS_SECRET_READ_PRIV_V1, - JSON_IDM_RADIUS_SERVERS_V1, + let idm_entries: Vec<&BuiltinGroup> = vec![ + &IDM_ALL_PERSONS, + &IDM_ALL_ACCOUNTS, + &IDM_PEOPLE_MANAGE_PRIV_V1, + &IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1, + &IDM_PEOPLE_EXTEND_PRIV_V1, + &IDM_PEOPLE_SELF_WRITE_MAIL_PRIV_V1, + &IDM_PEOPLE_WRITE_PRIV_V1, + &IDM_PEOPLE_READ_PRIV_V1, + &IDM_HP_PEOPLE_EXTEND_PRIV_V1, + &IDM_HP_PEOPLE_WRITE_PRIV_V1, + &IDM_HP_PEOPLE_READ_PRIV_V1, + &IDM_GROUP_MANAGE_PRIV_V1, + &IDM_GROUP_WRITE_PRIV_V1, + &IDM_GROUP_UNIX_EXTEND_PRIV_V1, + &IDM_ACCOUNT_MANAGE_PRIV_V1, + &IDM_ACCOUNT_WRITE_PRIV_V1, + &IDM_ACCOUNT_UNIX_EXTEND_PRIV_V1, + &IDM_ACCOUNT_READ_PRIV_V1, + &IDM_RADIUS_SECRET_WRITE_PRIV_V1, + &IDM_RADIUS_SECRET_READ_PRIV_V1, + &IDM_RADIUS_SERVERS_V1, // Write deps on read, so write must be added first. - JSON_IDM_HP_ACCOUNT_MANAGE_PRIV_V1, - JSON_IDM_HP_ACCOUNT_WRITE_PRIV_V1, - JSON_IDM_HP_ACCOUNT_READ_PRIV_V1, - JSON_IDM_HP_ACCOUNT_UNIX_EXTEND_PRIV_V1, - JSON_IDM_SCHEMA_MANAGE_PRIV_V1, - JSON_IDM_HP_GROUP_MANAGE_PRIV_V1, - JSON_IDM_HP_GROUP_WRITE_PRIV_V1, - JSON_IDM_HP_GROUP_UNIX_EXTEND_PRIV_V1, - JSON_IDM_ACP_MANAGE_PRIV_V1, - JSON_DOMAIN_ADMINS, - JSON_IDM_HP_OAUTH2_MANAGE_PRIV_V1, - JSON_IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV, - JSON_IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV, + &IDM_HP_ACCOUNT_MANAGE_PRIV_V1, + &IDM_HP_ACCOUNT_WRITE_PRIV_V1, + &IDM_HP_ACCOUNT_READ_PRIV_V1, + &IDM_HP_ACCOUNT_UNIX_EXTEND_PRIV_V1, + &IDM_SCHEMA_MANAGE_PRIV_V1, + &IDM_HP_GROUP_MANAGE_PRIV_V1, + &IDM_HP_GROUP_WRITE_PRIV_V1, + &IDM_HP_GROUP_UNIX_EXTEND_PRIV_V1, + &IDM_ACP_MANAGE_PRIV_V1, + &DOMAIN_ADMINS, + &IDM_HP_OAUTH2_MANAGE_PRIV_V1, + &IDM_HP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_PRIV, + &IDM_HP_SYNC_ACCOUNT_MANAGE_PRIV, // All members must exist before we write HP - JSON_IDM_HIGH_PRIVILEGE_V1, + &IDM_HIGH_PRIVILEGE_V1, + // other things + &IDM_UI_ENABLE_EXPERIMENTAL_FEATURES, + &IDM_ACCOUNT_MAIL_READ_PRIV, ]; let res: Result<(), _> = idm_entries - .iter() - .try_for_each(|e_str| self.internal_migrate_or_create_str(e_str)); + .into_iter() + .try_for_each(|e| self.internal_migrate_or_create(e.clone().try_into()?)); if res.is_ok() { admin_debug!("initialise_idm -> result Ok!"); } else { @@ -679,7 +678,7 @@ impl<'a> QueryServerWriteTransaction<'a> { let idm_entries: Vec = vec![ // Built in access controls. IDM_ADMINS_ACP_RECYCLE_SEARCH_V1.clone().into(), - E_IDM_ADMINS_ACP_REVIVE_V1.clone(), + IDM_ADMINS_ACP_REVIVE_V1.clone().into(), E_IDM_ALL_ACP_READ_V1.clone(), E_IDM_SELF_ACP_READ_V1.clone(), E_IDM_SELF_ACP_WRITE_V1.clone(), @@ -718,8 +717,6 @@ impl<'a> QueryServerWriteTransaction<'a> { E_IDM_ACP_RADIUS_SECRET_WRITE_PRIV_V1.clone(), E_IDM_HP_ACP_SERVICE_ACCOUNT_INTO_PERSON_MIGRATE_V1.clone(), E_IDM_HP_ACP_SYNC_ACCOUNT_MANAGE_PRIV_V1.clone(), - E_IDM_UI_ENABLE_EXPERIMENTAL_FEATURES.clone(), - E_IDM_ACCOUNT_MAIL_READ_PRIV.clone(), E_IDM_ACP_ACCOUNT_MAIL_READ_PRIV_V1.clone(), E_IDM_ACCOUNT_SELF_ACP_WRITE_V1.clone(), ]; diff --git a/server/lib/src/server/modify.rs b/server/lib/src/server/modify.rs index f2dd86cbb..3c1b7ac49 100644 --- a/server/lib/src/server/modify.rs +++ b/server/lib/src/server/modify.rs @@ -556,8 +556,9 @@ mod tests { assert!(server_txn.modify(&me_emp) == Err(OperationError::EmptyRequest)); // Mod changes no objects + // TODO: @yaleman fix this because we don't have a way to do this anymore let me_nochg = ModifyEvent::new_impersonate_entry_ser( - JSON_ADMIN_V1, + BUILTIN_ACCOUNT_IDM_ADMIN.clone(), filter!(f_eq( Attribute::Name, PartialValue::new_iname("flarbalgarble")