Appearance
🛡️ adminadmin@example.com · Domain admin in Acme Corp
Chapter 5 — Access through groups
The chapter in one line
Access is granted to roles, not to people.
The next six slides prove it by granting nothing to a user and watching the user gain access anyway.
A Project to share
bash
PROJECT=$(plexctl project create \
--domain "$DOMAIN_ID" \
--slug group-demo \
--display-name "Group Demo" \
--output json)
PROJECT_ID=$(echo "$PROJECT" | jq -r '.id')
echo "$PROJECT" | jq '{id, domain_id, slug, name}'Establish the baseline — you have nothing
bash
plexctl rebac check \
--subject "user:$USER_ID" \
--relation maintainer \
--resource "project:$PROJECT_ID"text
plexctl: rebac check: denied (reason=insufficient_relation, correlation_id=f8da0886-3ddc-430e-9f89-9a1778037a63)You created this Project moments ago and you are the Domain admin, and you still hold no maintainer on it.
Creating a thing does not silently grant you every relation on it.
A Group, and you in it
bash
GROUP=$(plexctl group create \
--domain "$DOMAIN_ID" \
--slug group-demo-operators \
--display-name "Group Demo Operators" \
--source manual \
--output json)
GROUP_ID=$(echo "$GROUP" | jq -r '.id')
echo "$GROUP" | jq '{id, domain_id, slug, display_name, source}'bash
plexctl group member add \
--group "$GROUP_ID" \
--principal "$USER_ID" \
--kind user \
--source manualStill nothing granted. The Group holds no relation on anything.
The key move
bash
plexctl rebac tuple add \
--project "$PROJECT_ID" \
--resource "project:$PROJECT_ID" \
--relation maintainer \
--subject "group:$GROUP_ID#member"Read the subject: group:<id>#member.
Not the Group object — the Group's member set. "Everyone who is a member of this Group holds maintainer on this Project."
That #member suffix is the whole idea.
The same check, a different answer
bash
plexctl rebac check \
--subject "user:$USER_ID" \
--relation maintainer \
--resource "project:$PROJECT_ID"text
DECISION REASON CORRELATION_ID
allowed 788330f3-d36e-4577-b187-eab964129c6eCharacter for character the command from three slides ago. denied became allowed, and nothing was granted to you.
Onboarding the next joiner is one group member add — not one tuple per Project.
What can this subject reach
bash
plexctl rebac lookup-resources \
--subject "user:$USER_ID" \
--relation maintainer \
--resource-type projecttext
OBJECT
019ecc67-2b3c-7d4e-8f50-1a2b3c4d5e6fWho can reach this resource
bash
plexctl rebac lookup-subjects \
--resource "project:$PROJECT_ID" \
--relation maintainer \
--subject-type usertext
OBJECT
019ecc65-9f3a-7c14-8d2b-5f3e0a7b1c40Neither query mentions the Group.
The engine has already expanded membership into concrete subjects and resources — which is exactly the shape an access review needs. Not "who is in which group", but "who can actually reach this".
Leave the Group
bash
plexctl group member remove \
--group "$GROUP_ID" \
--principal "$USER_ID" \
--kind userbash
plexctl rebac check \
--subject "user:$USER_ID" \
--relation maintainer \
--resource "project:$PROJECT_ID"text
plexctl: rebac check: denied (reason=insufficient_relation, correlation_id=f8da0886-3ddc-430e-9f89-9a1778037a63)The Project's grant never changed. You stopped being a member of the thing it was granted to.
Revoking a leaver across every Project a Group governs is one command.