added profile and memberof search to the basic model (#2712)

Co-authored-by: Firstyear <william@blackhats.net.au>
This commit is contained in:
Sebastiano Tocci 2024-04-23 02:30:38 +02:00 committed by GitHub
parent a0f743d8c8
commit 9354c180af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 90 additions and 18 deletions

View file

@ -68,6 +68,16 @@ pub async fn populate(_client: &KanidmOrcaClient, profile: Profile) -> Result<St
role: ActorRole::PeopleSelfWriteMail,
..Default::default()
},
Group {
name: "role_people_self_read_account".to_string(),
role: ActorRole::PeopleSelfReadProfile,
..Default::default()
},
Group {
name: "role_people_self_read_memberof".to_string(),
role: ActorRole::PeopleSelfReadMemberOf,
..Default::default()
},
];
// PHASE 3 - generate persons
@ -107,7 +117,6 @@ pub async fn populate(_client: &KanidmOrcaClient, profile: Profile) -> Result<St
let model = Model::Basic;
// =======
// Data is ready, make changes to the server. These should be idempotent if possible.
let p = Person {
preflight_state: PreflightState::Present,
@ -132,9 +141,9 @@ pub async fn populate(_client: &KanidmOrcaClient, profile: Profile) -> Result<St
// to each role always will exist and be operational.
for group in groups.iter_mut() {
// For now, our baseline is 50%. We can adjust this in future per
// For now, our baseline is 20%. We can adjust this in future per
// role for example.
let baseline = persons.len() / 2;
let baseline = persons.len() / 5;
let inverse = persons.len() - baseline;
// Randomly add extra from the inverse
let extra = Uniform::new(0, inverse);

View file

@ -13,6 +13,8 @@ pub enum TransitionAction {
Logout,
PrivilegeReauth,
WriteAttributePersonMail,
ReadSelfAccount,
ReadSelfMemberOf,
}
// Is this the right way? Should transitions/delay be part of the actor model? Should
@ -44,12 +46,16 @@ pub enum ActorRole {
None,
PeoplePiiReader,
PeopleSelfWriteMail,
PeopleSelfReadProfile,
PeopleSelfReadMemberOf,
}
impl ActorRole {
pub fn requires_membership_to(&self) -> Option<&[&str]> {
match self {
ActorRole::None => None,
ActorRole::None
| ActorRole::PeopleSelfReadProfile
| ActorRole::PeopleSelfReadMemberOf => None,
ActorRole::PeoplePiiReader => Some(&["idm_people_pii_read"]),
ActorRole::PeopleSelfWriteMail => Some(&["idm_people_self_write_mail"]),
}
@ -149,6 +155,38 @@ pub async fn logout(
))
}
pub async fn person_get_self_account(
client: &KanidmClient,
person: &Person,
) -> Result<(TransitionResult, EventRecord), Error> {
let start = Instant::now();
let result = client.idm_person_account_get(&person.username).await;
let duration = Instant::now().duration_since(start);
Ok(parse_call_result_into_transition_result_and_event_record(
result,
EventDetail::PersonGetSelfAccount,
start,
duration,
))
}
pub async fn person_get_self_memberof(
client: &KanidmClient,
person: &Person,
) -> Result<(TransitionResult, EventRecord), Error> {
let start = Instant::now();
let result = client
.idm_person_account_get_attr(&person.username, "memberof")
.await;
let duration = Instant::now().duration_since(start);
Ok(parse_call_result_into_transition_result_and_event_record(
result,
EventDetail::PersonGetSelfMemberOf,
start,
duration,
))
}
fn parse_call_result_into_transition_result_and_event_record<T>(
result: Result<T, ClientError>,
details: EventDetail,

View file

@ -51,6 +51,12 @@ impl ActorModel for ActorBasic {
let values = &[mail.as_str()];
model::person_set_self_mail(client, person, values).await
}
TransitionAction::ReadSelfAccount => {
model::person_get_self_account(client, person).await
}
TransitionAction::ReadSelfMemberOf => {
model::person_get_self_memberof(client, person).await
}
}?;
self.next_state(transition.action, result);
@ -61,28 +67,43 @@ impl ActorModel for ActorBasic {
impl ActorBasic {
fn next_transition(&mut self, roles: &BTreeSet<ActorRole>) -> Transition {
let logout_transition = Transition {
delay: Some(Duration::from_secs(5)),
action: TransitionAction::Logout,
};
match self.state {
State::Unauthenticated => Transition {
delay: None,
action: TransitionAction::Login,
},
// Doing some tests with more people I noticed that if the delay is too low somehow??! the server could start processing the reauth request before
// the auth one, yielding an error,
// TODO!!: understand why that happens
State::Authenticated => Transition {
delay: Some(Duration::from_millis(100)),
delay: Some(Duration::from_millis(1000)),
action: TransitionAction::PrivilegeReauth,
},
State::AuthenticatedWithReauth => {
if roles.contains(&ActorRole::PeopleSelfWriteMail) {
Transition {
// Since this is the basic model we don't want to get too fancy and do too many things, but since the struct Person
// already comes with a BTreeSet of roles we don't want to change that, so we arbitrarily choose to use just the first role
// (which is always deterministic thanks to the rng seed used to choose the roles)
State::AuthenticatedWithReauth => match roles.first() {
Some(role) => match role {
ActorRole::PeopleSelfWriteMail => Transition {
delay: Some(Duration::from_millis(200)),
action: TransitionAction::WriteAttributePersonMail,
}
} else {
Transition {
delay: Some(Duration::from_secs(5)),
action: TransitionAction::Logout,
}
}
}
},
ActorRole::PeopleSelfReadProfile => Transition {
delay: Some(Duration::from_millis(150)),
action: TransitionAction::ReadSelfAccount,
},
ActorRole::PeopleSelfReadMemberOf => Transition {
delay: Some(Duration::from_millis(330)),
action: TransitionAction::ReadSelfMemberOf,
},
ActorRole::PeoplePiiReader | ActorRole::None => logout_transition,
},
None => logout_transition,
},
}
}
@ -98,7 +119,9 @@ impl ActorBasic {
}
(
State::AuthenticatedWithReauth,
TransitionAction::WriteAttributePersonMail,
TransitionAction::WriteAttributePersonMail
| TransitionAction::ReadSelfAccount
| TransitionAction::ReadSelfMemberOf,
TransitionResult::Ok,
) => {
self.state = State::AuthenticatedWithReauth;

View file

@ -40,7 +40,7 @@ async fn preflight_person(
if let Some(need_groups) = role.requires_membership_to() {
for group_name in need_groups {
client
.group_add_members(&group_name, &[person.username.as_str()])
.group_add_members(group_name, &[person.username.as_str()])
.await?;
}
}

View file

@ -44,6 +44,8 @@ pub enum EventDetail {
Login,
Logout,
PersonSetSelfMail,
PersonGetSelfAccount,
PersonGetSelfMemberOf,
PersonReauth,
Error,
}