IDENTITY GOVERNANCE · LAB
Move people between jobs and find the access that stayed behind
Watch the HR Simulator move a person with their groups, move Ava by hand, query for access that no longer matches the job, trace where each grant came from, and end a handover on a date.
Partly readyUses your lab tenant
The lesson
Builds on: Why access needs governance, Sources of truth.
New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.
Partly ready. Most of this lab runs today. Steps that wait on platform features are marked, and Missing infrastructure says what they need.
- G23 Access requests and approvals, access reviews, JIT or temporary access
- G50 Access rules engine (attribute-based groups that recalculate, with a mass-removal guard)
Your progress
Press Start before you begin. Only events your tenant records after that count, in the order below. Checking reads your tenant's Audit, so you need Audit read access in it.
Sign in to start this lab and check your progress. Log in or create an account.
The source moves a person to a new department
Recorded as
scim.user.patchsucceeded forlab-hr-feed.The source moves their group membership too
Recorded as
scim.group.patchsucceeded forlab-hr-feed.Move Ava to moderation by hand
Recorded as
scim.user.patchsucceeded forlab-provisioningabout[email protected].Remove a group Ava no longer needs
Recorded as
scim.group.patchsucceeded forlab-provisioning.
Setup
Open a bash shell and set the variables and helpers from the directory lab, plus
HR_IDandHR_SECRET(read -rs) forlab-hr-feed.Make sure Ava's starting point matches the first governance lab: she is in
Print support,Print incident reviewsandPhoto moderation, the last added by hand. Add any that are missing in Groups. Then record her current department as print support.
export AVA=$(scim -G "$SCIM/Users" --data-urlencode 'filter=userName eq "[email protected]"' | jq -r '.Resources[0].id')
export CORA=$(scim -G "$SCIM/Users" --data-urlencode 'filter=userName eq "[email protected]"' | jq -r '.Resources[0].id')
group_id() { scim -G "$SCIM/Groups" --data-urlencode "filter=displayName eq \"$1\"" | jq -r '.Resources[0].id'; }
export PRINT=$(group_id "Print support") REVIEWS=$(group_id "Print incident reviews") MOD=$(group_id "Photo moderation")
jq -n --arg ent "$ENT" '{schemas:["urn:ietf:params:scim:api:messages:2.0:PatchOp"],Operations:[{op:"replace",path:($ent+":department"),value:"Print support"}]}' \
| scim -X PATCH "$SCIM/Users/$AVA" --data-binary @- | jq "{id, dept: .\"$ENT\".department}"
Press Start on the lab page.
In the HR Simulator, start a Full lifecycle run: 8 people, movers 25 percent, leavers 25 percent, 30 minutes, initial passwords on. Pause it once the joiner events have succeeded. The leaving lab continues this run.
Walkthrough
Before the move. In the run plan, find a "Mover: change department, title and manager" event and note its person's
externalId. Read them.
scim -G "$SCIM/Users" --data-urlencode 'filter=externalId eq "<the mover externalId>"' \
| jq ".Resources[0] | {id, title, groups: [.groups[]?.display], dept: .\"$ENT\".department, manager: .\"$ENT\".manager.value}"
Let the source move them. Use Advance until the mover event and its "Remove from group" and "Add to group" events succeed. Read the person again: new department, title, manager and group. Search Audit for the correlation ID shown in the event detail:
scim.user.patchlistsdepartment,titleandmanager, followed byscim.group.patchevents, all bylab-hr-feed.
Why it matters: this is "Recalculating access". When access follows the source, the removal happens in the same change as the addition, without anyone asking for it.
Move Ava the way a help desk would. Change her department and manager as
lab-provisioning, and touch nothing else.
jq -n --arg ent "$ENT" --arg cora "$CORA" '{schemas:["urn:ietf:params:scim:api:messages:2.0:PatchOp"],Operations:[
{op:"replace",path:($ent+":department"),value:"Photo moderation"},{op:"replace",path:($ent+":manager"),value:{value:$cora}}]}' \
| scim -X PATCH "$SCIM/Users/$AVA" --data-binary @- | jq '{id, groups: [.groups[]?.display]}'
Ava is now in moderation and still holds both print groups.
Why it matters: this is "Adding is easy, removing is not". The new access came from a phone call in the first lab. Nobody will call about the old access.
Find movers who kept old access.
scim -G "$SCIM/Users" --data-urlencode "filter=$ENT:department ne \"Print support\" and (groups[display eq \"Print support\"] or groups[display eq \"Print incident reviews\"])" \
--data-urlencode 'attributes=displayName,groups' | jq -r '.Resources[].displayName'
Ava comes back.
Why it matters: privilege creep becomes a query: a group that no longer matches the person's job.
Where did each grant come from? For each of Ava's three groups, search Audit for the group ID and read the actor of the change that added her: your BTL account or Ben in the portal (a manual grant), or a client. Fill the lesson's table:
| Access | How Ava got it | After the move |
|---|---|---|
| Print support | ||
| Print incident reviews | ||
| Photo moderation |
Why it matters: access that a source or rule granted recalculates when the job changes. Manual grants have no rule behind them, so they are the ones that stay behind.
A handover with an end. Decide that Ava keeps
Print supportfor two weeks to hand over her print orders, and write the end date in your notes. RemovePrint incident reviewsnow.
jq -n --arg u "$AVA" '{schemas:["urn:ietf:params:scim:api:messages:2.0:PatchOp"],Operations:[{op:"remove",path:("members[value eq \""+$u+"\"]")}]}' \
| scim -X PATCH "$SCIM/Groups/$REVIEWS" --data-binary @- -o /dev/null -w '%{http_code}\n'
At the end of this lab, standing in for the end date, remove her from Print support the same way with $PRINT.
Why it matters: this is "An overlap with an end". "Keep it for now" becomes permanent unless the end is set at the start. Here the end lives only in your notes, which is the weakness G23 would fix.
Quieter changes. First a name change: replace Mia's
name.familyNamewithLane-Okoro(find her withfilter=externalId eq "E10482"). Read her back: sameid, same groups. Then change only Ava's manager, from Cora to Ben (filter=userName eq "[email protected]"gives his ID).
Why it matters: a name change is not a leaver plus a joiner, and a manager change reroutes approvals and reviews even when nothing else moves.
Planned walkthrough
Once G23 and G50 exist, the same move runs without your notes or your script.
In Groups, add Ava to
Print supportas a time-bound membership: reason "Handover of print orders after moving to moderation", owner Cora, end date two weeks out. Audit records the grant with its reason and end date.Create an access rule "department eq Print support grants Print support". Step 3's department change then removes Ava's rule-granted membership at once, while the time-bound membership keeps the group until its end date.
On the end date the tenant removes the membership by itself, and Audit records the expiry with the grant it ends.
Break it
Run the step 6 removal again. The answer is still a success and the group is unchanged: this service treats removing a non-member as done. Read the group to confirm, as the lesson recommends, rather than trusting the status alone.
See why replacing a whole member list is avoided. Create a group
lab-tmp-scratchin the portal with Ava, Ben and Cora, then replace its members with a list that names only Ava.
export SCRATCH=$(group_id "lab-tmp-scratch")
jq -n --arg u "$AVA" '{schemas:["urn:ietf:params:scim:api:messages:2.0:PatchOp"],Operations:[{op:"replace",path:"members",value:[{value:$u}]}]}' \
| scim -X PATCH "$SCIM/Groups/$SCRATCH" --data-binary @- -o /dev/null -w '%{http_code}\n'
Ben and Cora are gone, and nobody decided to remove them.
Restore: delete lab-tmp-scratch in Groups.
Check your work
Press Check my progress. The checks look for, in order:
scim.user.patchsucceeded bylab-hr-feed(step 2)scim.group.patchsucceeded bylab-hr-feed(step 2)scim.user.patchsucceeded bylab-provisioningon Ava (step 3)scim.group.patchsucceeded bylab-provisioning(step 6)
After Cleanup, the step 4 query returns nobody.
Cleanup
Remove Ava from
Print support(the end of the handover). She keepsPhoto moderation.Set Mia's family name back to
Laneand Ava's manager back to Cora.Leave the lifecycle run paused for the leaving lab.
Missing infrastructure
G23: a time-bound membership with an end date, owner and reason would make step 6's handover end by itself and show up as a labeled exception in reviews.
G50: rules that recalculate group membership from
departmentwould remove the print groups as soon as step 3 changed Ava's department, as the HR Simulator's own group moves do in step 2.