MemberOf in search implies DirectMemberOf (#3024)

This commit is contained in:
Firstyear 2024-09-04 22:19:40 +10:00 committed by GitHub
parent db26979a98
commit e5a5de8de3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 2 deletions

View file

@ -3134,4 +3134,51 @@ mod tests {
// Test reject delete, can not delete due to system protection
test_acp_delete!(&de_account, vec![acp], &r_set, false);
}
#[test]
fn test_access_sync_memberof_implies_directmemberof() {
sketching::test_init();
let ev1 = entry_init!(
(Attribute::Class, EntryClass::Object.to_value()),
(Attribute::Name, Value::new_iname("test_account_1")),
(Attribute::Uuid, Value::Uuid(UUID_TEST_ACCOUNT_1)),
(Attribute::MemberOf, Value::Refer(UUID_TEST_GROUP_1)),
(Attribute::DirectMemberOf, Value::Refer(UUID_TEST_GROUP_1))
)
.into_sealed_committed();
let r_set = vec![Arc::new(ev1)];
let exv1 = entry_init!(
(Attribute::Name, Value::new_iname("test_account_1")),
(Attribute::MemberOf, Value::Refer(UUID_TEST_GROUP_1)),
(Attribute::DirectMemberOf, Value::Refer(UUID_TEST_GROUP_1))
)
.into_sealed_committed();
let ex_anon_some = vec![exv1];
let se_anon_ro = SearchEvent::new_impersonate_identity(
Identity::from_impersonate_entry_readonly(E_TEST_ACCOUNT_1.clone()),
filter_all!(f_pres(Attribute::Name)),
);
let acp = AccessControlSearch::from_raw(
"test_acp",
Uuid::new_v4(),
// apply to all accounts.
UUID_TEST_GROUP_1,
// Allow anonymous to read only testperson1
filter_valid!(f_eq(
Attribute::Uuid,
PartialValue::Uuid(UUID_TEST_ACCOUNT_1)
)),
// May query on name, and see memberof. MemberOf implies direct
// memberof.
format!("{} {}", Attribute::Name, Attribute::MemberOf).as_str(),
);
// Finally test it!
test_acp_search_reduce!(&se_anon_ro, vec![acp], r_set, ex_anon_some);
}
}

View file

@ -35,7 +35,7 @@ impl AccessControlSearch {
)));
}
let attrs = value
let mut attrs: BTreeSet<_> = value
.get_ava_iter_iutf8(Attribute::AcpSearchAttr)
.ok_or_else(|| {
admin_error!("Missing {}", Attribute::AcpSearchAttr);
@ -44,6 +44,11 @@ impl AccessControlSearch {
.map(AttrString::from)
.collect();
// Ability to search memberof, implies the ability to read directmemberof
if attrs.contains(Attribute::MemberOf.as_ref()) {
attrs.insert(Attribute::DirectMemberOf.into());
}
let acp = AccessControlProfile::try_from(qs, value)?;
Ok(AccessControlSearch { acp, attrs })
@ -59,6 +64,13 @@ impl AccessControlSearch {
targetscope: Filter<FilterValid>,
attrs: &str,
) -> Self {
let mut attrs: BTreeSet<_> = attrs.split_whitespace().map(AttrString::from).collect();
// Ability to search memberof, implies the ability to read directmemberof
if attrs.contains(Attribute::MemberOf.as_ref()) {
attrs.insert(Attribute::DirectMemberOf.into());
}
AccessControlSearch {
acp: AccessControlProfile {
name: name.to_string(),
@ -66,7 +78,7 @@ impl AccessControlSearch {
receiver: AccessControlReceiver::Group(btreeset!(receiver)),
target: AccessControlTarget::Scope(targetscope),
},
attrs: attrs.split_whitespace().map(AttrString::from).collect(),
attrs,
}
}