Review feedback

This commit is contained in:
William Brown 2025-03-28 14:11:55 +10:00
parent a9c2e9f8da
commit 229f0514d4
9 changed files with 189 additions and 195 deletions

74
Cargo.lock generated
View file

@ -232,9 +232,9 @@ dependencies = [
[[package]]
name = "async-compression"
version = "0.4.21"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0cf008e5e1a9e9e22a7d3c9a4992e21a350290069e36d8fb72304ed17e8f2d2"
checksum = "59a194f9d963d8099596278594b3107448656ba73831c9d8c783e613ce86da64"
dependencies = [
"flate2",
"futures-core",
@ -724,9 +724,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.32"
version = "4.5.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
dependencies = [
"clap_builder",
"clap_derive",
@ -734,9 +734,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.32"
version = "4.5.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
dependencies = [
"anstream",
"anstyle",
@ -1167,9 +1167,9 @@ dependencies = [
[[package]]
name = "deranged"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058"
dependencies = [
"powerfmt",
"serde",
@ -1441,13 +1441,12 @@ dependencies = [
[[package]]
name = "fantoccini"
version = "0.21.4"
version = "0.21.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7722aeee9c2be6fa131166990295089d73d973012b758a2208b9ba51af5dd024"
checksum = "e3a6a7a9a454c24453f9807c7f12b37e31ae43f3eb41888ae1f79a9a3e3be3f5"
dependencies = [
"base64 0.22.1",
"cookie 0.18.1",
"futures-core",
"futures-util",
"http 1.3.1",
"http-body-util",
@ -2533,14 +2532,15 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.61"
version = "0.1.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
@ -2595,9 +2595,9 @@ dependencies = [
[[package]]
name = "icu_locid_transform_data"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
[[package]]
name = "icu_normalizer"
@ -2619,9 +2619,9 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
[[package]]
name = "icu_properties"
@ -2640,9 +2640,9 @@ dependencies = [
[[package]]
name = "icu_properties_data"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
[[package]]
name = "icu_provider"
@ -2843,9 +2843,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.29.0"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c59cb1733c34377b6067a0419befd7f25073c5249ec3b0614a482bf499e1df5"
checksum = "161c33c3ec738cfea3288c5c53dfcdb32fd4fc2954de86ea06f71b5a1a40bfcd"
dependencies = [
"ahash",
"base64 0.22.1",
@ -3493,9 +3493,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.26"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "lru"
@ -3967,9 +3967,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.21.1"
version = "1.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b"
[[package]]
name = "openssl"
@ -4502,9 +4502,9 @@ dependencies = [
[[package]]
name = "quinn-udp"
version = "0.5.10"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944"
checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5"
dependencies = [
"cfg_aliases",
"libc",
@ -4637,9 +4637,9 @@ checksum = "5daffa8f5ca827e146485577fa9dba9bd9c6921e06e954ab8f6408c10f753086"
[[package]]
name = "referencing"
version = "0.29.0"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce52678d53e5ee37e4af0a9036ca834d0cd34b33c82457c6b06a24f8d783344"
checksum = "40a64b3a635fad9000648b4d8a59c8710c523ab61a23d392a7d91d47683f5adc"
dependencies = [
"ahash",
"fluent-uri",
@ -4966,9 +4966,9 @@ dependencies = [
[[package]]
name = "rustls-webpki"
version = "0.103.0"
version = "0.103.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f"
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
dependencies = [
"ring",
"rustls-pki-types",
@ -5595,9 +5595,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.40"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
dependencies = [
"deranged",
"itoa",
@ -5618,9 +5618,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
[[package]]
name = "time-macros"
version = "0.2.21"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04"
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
dependencies = [
"num-conv",
"time-core",
@ -6482,9 +6482,9 @@ dependencies = [
[[package]]
name = "whoami"
version = "1.5.2"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d"
checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7"
dependencies = [
"redox_syscall",
"wasite",

View file

@ -33,7 +33,7 @@ pub enum ScimAttributeEffectiveAccess {
/// All attributes on the entry have this permission granted
Grant,
/// All attributes on the entry have this permission denied
Denied,
Deny,
/// The following attributes on the entry have this permission granted
Allow(BTreeSet<Attribute>),
}
@ -43,7 +43,7 @@ impl ScimAttributeEffectiveAccess {
pub fn check(&self, attr: &Attribute) -> bool {
match self {
Self::Grant => true,
Self::Denied => false,
Self::Deny => false,
Self::Allow(set) => set.contains(attr),
}
}

View file

@ -599,19 +599,19 @@ impl IdmServerProxyWriteTransaction<'_> {
}
let eperm_search_primary_cred = match &eperm.search {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::PrimaryCredential),
};
let eperm_mod_primary_cred = match &eperm.modify_pres {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::PrimaryCredential),
};
let eperm_rem_primary_cred = match &eperm.modify_rem {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::PrimaryCredential),
};
@ -620,19 +620,19 @@ impl IdmServerProxyWriteTransaction<'_> {
eperm_search_primary_cred && eperm_mod_primary_cred && eperm_rem_primary_cred;
let eperm_search_passkeys = match &eperm.search {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::PassKeys),
};
let eperm_mod_passkeys = match &eperm.modify_pres {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::PassKeys),
};
let eperm_rem_passkeys = match &eperm.modify_rem {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::PassKeys),
};
@ -640,19 +640,19 @@ impl IdmServerProxyWriteTransaction<'_> {
let passkeys_can_edit = eperm_search_passkeys && eperm_mod_passkeys && eperm_rem_passkeys;
let eperm_search_attested_passkeys = match &eperm.search {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::AttestedPasskeys),
};
let eperm_mod_attested_passkeys = match &eperm.modify_pres {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::AttestedPasskeys),
};
let eperm_rem_attested_passkeys = match &eperm.modify_rem {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::AttestedPasskeys),
};
@ -662,19 +662,19 @@ impl IdmServerProxyWriteTransaction<'_> {
&& eperm_rem_attested_passkeys;
let eperm_search_unixcred = match &eperm.search {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::UnixPassword),
};
let eperm_mod_unixcred = match &eperm.modify_pres {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::UnixPassword),
};
let eperm_rem_unixcred = match &eperm.modify_rem {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::UnixPassword),
};
@ -685,19 +685,19 @@ impl IdmServerProxyWriteTransaction<'_> {
&& eperm_rem_unixcred;
let eperm_search_sshpubkey = match &eperm.search {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::SshPublicKey),
};
let eperm_mod_sshpubkey = match &eperm.modify_pres {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::SshPublicKey),
};
let eperm_rem_sshpubkey = match &eperm.modify_rem {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::SshPublicKey),
};
@ -726,7 +726,7 @@ impl IdmServerProxyWriteTransaction<'_> {
})?;
match &eperm.search {
Access::Denied => false,
Access::Deny => false,
Access::Grant => true,
Access::Allow(attrs) => attrs.contains(&Attribute::SyncCredentialPortal),
}

View file

@ -6,12 +6,12 @@ use crate::prelude::*;
use std::collections::BTreeSet;
pub(super) enum CreateResult {
Denied,
Deny,
Grant,
}
enum IResult {
Denied,
Deny,
Grant,
Ignore,
}
@ -26,25 +26,25 @@ pub(super) fn apply_create_access<'a>(
// This module can never yield a grant.
match protected_filter_entry(ident, entry) {
IResult::Denied => denied = true,
IResult::Deny => denied = true,
IResult::Grant | IResult::Ignore => {}
}
match create_filter_entry(ident, related_acp, entry) {
IResult::Denied => denied = true,
IResult::Deny => denied = true,
IResult::Grant => grant = true,
IResult::Ignore => {}
}
if denied {
// Something explicitly said no.
CreateResult::Denied
CreateResult::Deny
} else if grant {
// Something said yes
CreateResult::Grant
} else {
// Nothing said yes.
CreateResult::Denied
CreateResult::Deny
}
}
@ -61,7 +61,7 @@ fn create_filter_entry<'a>(
}
IdentType::Synch(_) => {
security_critical!("Blocking sync check");
return IResult::Denied;
return IResult::Deny;
}
IdentType::User(_) => {}
};
@ -70,7 +70,7 @@ fn create_filter_entry<'a>(
match ident.access_scope() {
AccessScope::ReadOnly | AccessScope::Synchronise => {
security_access!("denied ❌ - identity access scope is not permitted to create");
return IResult::Denied;
return IResult::Deny;
}
AccessScope::ReadWrite => {
// As you were
@ -97,7 +97,7 @@ fn create_filter_entry<'a>(
Some(s) => s.collect(),
None => {
admin_error!("Class set failed to build - corrupted entry?");
return IResult::Denied;
return IResult::Deny;
}
};
@ -174,7 +174,7 @@ fn protected_filter_entry(ident: &Identity, entry: &Entry<EntryInit, EntryNew>)
}
IdentType::Synch(_) => {
security_access!("sync agreements may not directly create entities");
IResult::Denied
IResult::Deny
}
IdentType::User(_) => {
// Now check things ...
@ -185,7 +185,7 @@ fn protected_filter_entry(ident: &Identity, entry: &Entry<EntryInit, EntryNew>)
} else {
// Block the mod, something is present
security_access!("attempt to create with protected class type");
IResult::Denied
IResult::Deny
}
} else {
// Nothing to check - this entry will fail to create anyway because it has

View file

@ -6,12 +6,12 @@ use crate::prelude::*;
use std::sync::Arc;
pub(super) enum DeleteResult {
Denied,
Deny,
Grant,
}
enum IResult {
Denied,
Deny,
Grant,
Ignore,
}
@ -25,25 +25,25 @@ pub(super) fn apply_delete_access<'a>(
let mut grant = false;
match protected_filter_entry(ident, entry) {
IResult::Denied => denied = true,
IResult::Deny => denied = true,
IResult::Grant | IResult::Ignore => {}
}
match delete_filter_entry(ident, related_acp, entry) {
IResult::Denied => denied = true,
IResult::Deny => denied = true,
IResult::Grant => grant = true,
IResult::Ignore => {}
}
if denied {
// Something explicitly said no.
DeleteResult::Denied
DeleteResult::Deny
} else if grant {
// Something said yes
DeleteResult::Grant
} else {
// Nothing said yes.
DeleteResult::Denied
DeleteResult::Deny
}
}
@ -60,7 +60,7 @@ fn delete_filter_entry<'a>(
}
IdentType::Synch(_) => {
security_critical!("Blocking sync check");
return IResult::Denied;
return IResult::Deny;
}
IdentType::User(_) => {}
};
@ -69,7 +69,7 @@ fn delete_filter_entry<'a>(
match ident.access_scope() {
AccessScope::ReadOnly | AccessScope::Synchronise => {
security_access!("denied ❌ - identity access scope is not permitted to delete");
return IResult::Denied;
return IResult::Deny;
}
AccessScope::ReadWrite => {
// As you were
@ -153,13 +153,13 @@ fn protected_filter_entry(ident: &Identity, entry: &Arc<EntrySealedCommitted>) -
}
IdentType::Synch(_) => {
security_access!("sync agreements may not directly delete entities");
IResult::Denied
IResult::Deny
}
IdentType::User(_) => {
// Prevent deletion of entries that exist in the system controlled entry range.
if entry.get_uuid() <= UUID_ANONYMOUS {
security_access!("attempt to delete system builtin entry");
return IResult::Denied;
return IResult::Deny;
}
// Prevent deleting some protected types.
@ -170,7 +170,7 @@ fn protected_filter_entry(ident: &Identity, entry: &Arc<EntrySealedCommitted>) -
} else {
// Block the mod, something is present
security_access!("attempt to create with protected class type");
IResult::Denied
IResult::Deny
}
} else {
// Nothing to check - this entry will fail to create anyway because it has

View file

@ -56,7 +56,7 @@ mod search;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Access {
Grant,
Denied,
Deny,
Allow(BTreeSet<Attribute>),
}
@ -64,7 +64,7 @@ impl From<&Access> for ScimAttributeEffectiveAccess {
fn from(value: &Access) -> Self {
match value {
Access::Grant => Self::Grant,
Access::Denied => Self::Denied,
Access::Deny => Self::Deny,
Access::Allow(set) => Self::Allow(set.clone()),
}
}
@ -73,7 +73,7 @@ impl From<&Access> for ScimAttributeEffectiveAccess {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AccessClass {
Grant,
Denied,
Deny,
Allow(BTreeSet<AttrString>),
}
@ -93,7 +93,7 @@ pub struct AccessEffectivePermission {
pub enum AccessBasicResult {
// Deny this operation unconditionally.
Denied,
Deny,
// Unbounded allow, provided no deny state exists.
Grant,
// This module makes no decisions about this entry.
@ -102,7 +102,7 @@ pub enum AccessBasicResult {
pub enum AccessSrchResult {
// Deny this operation unconditionally.
Denied,
Deny,
// Unbounded allow, provided no deny state exists.
Grant,
// This module makes no decisions about this entry.
@ -120,7 +120,7 @@ pub enum AccessSrchResult {
pub enum AccessModResult<'a> {
// Deny this operation unconditionally.
Denied,
Deny,
// Unbounded allow, provided no deny state exists.
// Grant,
// This module makes no decisions about this entry.
@ -327,7 +327,7 @@ pub trait AccessControlsTransaction<'a> {
.into_iter()
.filter(|e| {
match apply_search_access(ident, related_acp.as_slice(), e) {
SearchResult::Denied => false,
SearchResult::Deny => false,
SearchResult::Grant => true,
SearchResult::Allow(allowed_attrs) => {
// The allow set constrained.
@ -425,7 +425,7 @@ pub trait AccessControlsTransaction<'a> {
.into_iter()
.filter_map(|entry| {
match apply_search_access(&se.ident, &search_related_acp, &entry) {
SearchResult::Denied => {
SearchResult::Deny => {
None
}
SearchResult::Grant => {
@ -607,7 +607,7 @@ pub trait AccessControlsTransaction<'a> {
debug!(entry_id = %e.get_display_id());
match apply_modify_access(&me.ident, related_acp.as_slice(), sync_agmts, e) {
ModifyResult::Denied => false,
ModifyResult::Deny => false,
ModifyResult::Grant => true,
ModifyResult::Allow {
pres,
@ -763,7 +763,7 @@ pub trait AccessControlsTransaction<'a> {
let sync_agmts = self.get_sync_agreements();
match apply_modify_access(&me.ident, related_acp.as_slice(), sync_agmts, e) {
ModifyResult::Denied => false,
ModifyResult::Deny => false,
ModifyResult::Grant => true,
ModifyResult::Allow {
pres,
@ -862,7 +862,7 @@ pub trait AccessControlsTransaction<'a> {
// For each entry
let r = entries.iter().all(|e| {
match apply_create_access(&ce.ident, related_acp.as_slice(), e) {
CreateResult::Denied => false,
CreateResult::Deny => false,
CreateResult::Grant => true,
}
});
@ -918,7 +918,7 @@ pub trait AccessControlsTransaction<'a> {
// For each entry
let r = entries.iter().all(|e| {
match apply_delete_access(&de.ident, related_acp.as_slice(), e) {
DeleteResult::Denied => false,
DeleteResult::Deny => false,
DeleteResult::Grant => true,
}
});
@ -1007,7 +1007,7 @@ pub trait AccessControlsTransaction<'a> {
) -> AccessEffectivePermission {
// == search ==
let search_effective = match apply_search_access(ident, search_related_acp, entry) {
SearchResult::Denied => Access::Denied,
SearchResult::Deny => Access::Deny,
SearchResult::Grant => Access::Grant,
SearchResult::Allow(allowed_attrs) => {
// Bound by requested attrs?
@ -1018,11 +1018,11 @@ pub trait AccessControlsTransaction<'a> {
// == modify ==
let (modify_pres, modify_rem, modify_pres_class, modify_rem_class) =
match apply_modify_access(ident, modify_related_acp, sync_agmts, entry) {
ModifyResult::Denied => (
Access::Denied,
Access::Denied,
AccessClass::Denied,
AccessClass::Denied,
ModifyResult::Deny => (
Access::Deny,
Access::Deny,
AccessClass::Deny,
AccessClass::Deny,
),
ModifyResult::Grant => (
Access::Grant,
@ -1047,7 +1047,7 @@ pub trait AccessControlsTransaction<'a> {
let delete_status = apply_delete_access(ident, delete_related_acp, entry);
let delete = match delete_status {
DeleteResult::Denied => false,
DeleteResult::Deny => false,
DeleteResult::Grant => true,
};
@ -2283,8 +2283,8 @@ mod tests {
"member class",
// Allow rem name and class
"member class",
"group",
"group",
EntryClass::Group.into(),
EntryClass::Group.into(),
);
// Does not have a pres or rem class in attrs
let acp_no_class = AccessControlModify::from_raw(
@ -2302,8 +2302,8 @@ mod tests {
// Allow rem name and class
"name class",
// And the class allowed is NOT an account ...
"group",
"group",
EntryClass::Group.into(),
EntryClass::Group.into(),
);
// Test allowed pres

View file

@ -13,7 +13,7 @@ use std::collections::BTreeSet;
use std::sync::Arc;
pub(super) enum ModifyResult<'a> {
Denied,
Deny,
Grant,
Allow {
pres: BTreeSet<Attribute>,
@ -52,14 +52,14 @@ pub(super) fn apply_modify_access<'a>(
// kind of being three operations all in one.
match modify_ident_test(ident) {
AccessBasicResult::Denied => denied = true,
AccessBasicResult::Deny => denied = true,
AccessBasicResult::Grant => grant = true,
AccessBasicResult::Ignore => {}
}
// Check with protected if we should proceed.
match modify_protected_attrs(ident, entry) {
AccessModResult::Denied => denied = true,
AccessModResult::Deny => denied = true,
AccessModResult::Constrain {
mut pres_attr,
mut rem_attr,
@ -86,7 +86,7 @@ pub(super) fn apply_modify_access<'a>(
if !grant && !denied {
// If it's a sync entry, constrain it.
match modify_sync_constrain(ident, entry, sync_agreements) {
AccessModResult::Denied => denied = true,
AccessModResult::Deny => denied = true,
AccessModResult::Constrain {
mut pres_attr,
mut rem_attr,
@ -156,7 +156,7 @@ pub(super) fn apply_modify_access<'a>(
.collect();
match modify_pres_test(scoped_acp.as_slice()) {
AccessModResult::Denied => denied = true,
AccessModResult::Deny => denied = true,
// Can never return a unilateral grant.
// AccessModResult::Grant => {}
AccessModResult::Ignore => {}
@ -176,7 +176,7 @@ pub(super) fn apply_modify_access<'a>(
}
if denied {
ModifyResult::Denied
ModifyResult::Deny
} else if grant {
ModifyResult::Grant
} else {
@ -235,7 +235,7 @@ fn modify_ident_test(ident: &Identity) -> AccessBasicResult {
}
IdentType::Synch(_) => {
security_critical!("Blocking sync check");
return AccessBasicResult::Denied;
return AccessBasicResult::Deny;
}
IdentType::User(_) => {}
};
@ -244,7 +244,7 @@ fn modify_ident_test(ident: &Identity) -> AccessBasicResult {
match ident.access_scope() {
AccessScope::ReadOnly | AccessScope::Synchronise => {
security_access!("denied ❌ - identity access scope is not permitted to modify");
return AccessBasicResult::Denied;
return AccessBasicResult::Deny;
}
AccessScope::ReadWrite => {
// As you were
@ -328,7 +328,7 @@ fn modify_sync_constrain<'a>(
}
} else {
warn!(entry = ?entry.get_uuid(), "sync_parent_uuid not found on sync object, preventing all access");
AccessModResult::Denied
AccessModResult::Deny
}
}
}
@ -369,7 +369,7 @@ fn modify_protected_entry_attrs<'a>(classes: &BTreeSet<String>) -> AccessModResu
// First check for the hard-deny rules.
if !classes.is_disjoint(&LOCKED_ENTRY_CLASSES) {
// Hard deny attribute modifications to these types.
return AccessModResult::Denied;
return AccessModResult::Deny;
}
let mut constrain_attrs = BTreeSet::default();
@ -422,7 +422,7 @@ fn modify_protected_entry_attrs<'a>(classes: &BTreeSet<String>) -> AccessModResu
// If we don't constrain the attributes at all, we have to deny the change
// from proceeding.
if constrain_attrs.is_empty() {
AccessModResult::Denied
AccessModResult::Deny
} else {
AccessModResult::Constrain {
pres_attr: constrain_attrs.clone(),

View file

@ -1,89 +1,83 @@
use crate::prelude::EntryClass;
use std::collections::BTreeSet;
use std::sync::LazyLock;
lazy_static! {
/// These entry classes may not be created or deleted, and may invoke some protection rules
/// if on an entry.
pub static ref PROTECTED_ENTRY_CLASSES: BTreeSet<String> = {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
EntryClass::SyncObject,
EntryClass::Tombstone,
EntryClass::Recycled,
];
/// These entry classes may not be created or deleted, and may invoke some protection rules
/// if on an entry.
pub static PROTECTED_ENTRY_CLASSES: LazyLock<BTreeSet<String>> = LazyLock::new(|| {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
EntryClass::SyncObject,
EntryClass::Tombstone,
EntryClass::Recycled,
];
BTreeSet::from_iter(classes.into_iter()
.map(|ec| ec.into()))
};
BTreeSet::from_iter(classes.into_iter().map(|ec| ec.into()))
});
/// Entries with these classes are protected from modifications - not that
/// sync object is not present here as there are separate rules for that in
/// the modification access module.
///
/// Recycled is also not protected here as it needs to be able to be removed
/// by a recycle bin admin.
pub static ref PROTECTED_MOD_ENTRY_CLASSES: BTreeSet<String> = {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
// EntryClass::SyncObject,
EntryClass::Tombstone,
EntryClass::Recycled,
];
/// Entries with these classes are protected from modifications - not that
/// sync object is not present here as there are separate rules for that in
/// the modification access module.
///
/// Recycled is also not protected here as it needs to be able to be removed
/// by a recycle bin admin.
pub static PROTECTED_MOD_ENTRY_CLASSES: LazyLock<BTreeSet<String>> = LazyLock::new(|| {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
// EntryClass::SyncObject,
EntryClass::Tombstone,
EntryClass::Recycled,
];
BTreeSet::from_iter(classes.into_iter()
.map(|ec| ec.into()))
};
BTreeSet::from_iter(classes.into_iter().map(|ec| ec.into()))
});
/// These classes may NOT be added to ANY ENTRY
pub static ref PROTECTED_MOD_PRES_ENTRY_CLASSES: BTreeSet<String> = {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
EntryClass::SyncObject,
EntryClass::Tombstone,
EntryClass::Recycled,
];
/// These classes may NOT be added to ANY ENTRY
pub static PROTECTED_MOD_PRES_ENTRY_CLASSES: LazyLock<BTreeSet<String>> = LazyLock::new(|| {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
EntryClass::SyncObject,
EntryClass::Tombstone,
EntryClass::Recycled,
];
BTreeSet::from_iter(classes.into_iter()
.map(|ec| ec.into()))
};
BTreeSet::from_iter(classes.into_iter().map(|ec| ec.into()))
});
/// These classes may NOT be removed from ANY ENTRY
pub static ref PROTECTED_MOD_REM_ENTRY_CLASSES: BTreeSet<String> = {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
EntryClass::SyncObject,
EntryClass::Tombstone,
// EntryClass::Recycled,
];
/// These classes may NOT be removed from ANY ENTRY
pub static PROTECTED_MOD_REM_ENTRY_CLASSES: LazyLock<BTreeSet<String>> = LazyLock::new(|| {
let classes = vec![
EntryClass::System,
EntryClass::DomainInfo,
EntryClass::SystemInfo,
EntryClass::SystemConfig,
EntryClass::DynGroup,
EntryClass::SyncObject,
EntryClass::Tombstone,
// EntryClass::Recycled,
];
BTreeSet::from_iter(classes.into_iter()
.map(|ec| ec.into()))
};
BTreeSet::from_iter(classes.into_iter().map(|ec| ec.into()))
});
/// Entries with these classes may not be modified under any circumstance.
pub static ref LOCKED_ENTRY_CLASSES: BTreeSet<String> = {
let classes = vec![
EntryClass::Tombstone,
// EntryClass::Recycled,
];
/// Entries with these classes may not be modified under any circumstance.
pub static LOCKED_ENTRY_CLASSES: LazyLock<BTreeSet<String>> = LazyLock::new(|| {
let classes = vec![
EntryClass::Tombstone,
// EntryClass::Recycled,
];
BTreeSet::from_iter(classes.into_iter()
.map(|ec| ec.into()))
};
}
BTreeSet::from_iter(classes.into_iter().map(|ec| ec.into()))
});

View file

@ -8,7 +8,7 @@ use super::AccessSrchResult;
use std::sync::Arc;
pub(super) enum SearchResult {
Denied,
Deny,
Grant,
Allow(BTreeSet<Attribute>),
}
@ -28,7 +28,7 @@ pub(super) fn apply_search_access(
// The access control profile
match search_filter_entry(ident, related_acp, entry) {
AccessSrchResult::Denied => denied = true,
AccessSrchResult::Deny => denied = true,
AccessSrchResult::Grant => grant = true,
AccessSrchResult::Ignore => {}
// AccessSrchResult::Constrain { mut attr } => constrain.append(&mut attr),
@ -36,7 +36,7 @@ pub(super) fn apply_search_access(
};
match search_oauth2_filter_entry(ident, entry) {
AccessSrchResult::Denied => denied = true,
AccessSrchResult::Deny => denied = true,
AccessSrchResult::Grant => grant = true,
AccessSrchResult::Ignore => {}
// AccessSrchResult::Constrain { mut attr } => constrain.append(&mut attr),
@ -44,7 +44,7 @@ pub(super) fn apply_search_access(
};
match search_sync_account_filter_entry(ident, entry) {
AccessSrchResult::Denied => denied = true,
AccessSrchResult::Deny => denied = true,
AccessSrchResult::Grant => grant = true,
AccessSrchResult::Ignore => {}
// AccessSrchResult::Constrain{ mut attr } => constrain.append(&mut attr),
@ -56,7 +56,7 @@ pub(super) fn apply_search_access(
// Now finalise the decision.
if denied {
SearchResult::Denied
SearchResult::Deny
} else if grant {
SearchResult::Grant
} else {
@ -84,7 +84,7 @@ fn search_filter_entry(
}
IdentType::Synch(_) => {
security_debug!(uuid = ?entry.get_display_id(), "Blocking sync check");
return AccessSrchResult::Denied;
return AccessSrchResult::Deny;
}
IdentType::User(_) => {}
};
@ -95,7 +95,7 @@ fn search_filter_entry(
security_debug!(
"denied ❌ - identity access scope 'Synchronise' is not permitted to search"
);
return AccessSrchResult::Denied;
return AccessSrchResult::Deny;
}
AccessScope::ReadOnly | AccessScope::ReadWrite => {
// As you were