Skip to main content

Add or remove users on a rule

Add or remove the people a rule applies to. You can put users (or user groups) directly on the rule's scope, or manage a local user group and reference it from the rule. Same outcome, different operational trade-offs.

Use this when:

  • You want to change who a rule covers from automation.
  • You are deciding whether to scope a rule by individual users or by a managed group.

Prerequisites: a Super User service account and the environment variables from Getting started. Read Policy overview, User groups, and Delta patch first.

export RULE_ID='0RLEXAMPLERULEXXXXXXXXXXXXXX'

Approaches

ApproachHow it worksBest whenTradeoffs
A. Directly on the ruleAdd/remove users and user groups in the rule's scope via delta patchA small, rule-specific audienceThe rule object changes on every membership edit; not reusable
B. Via a local user groupManage one local user group; reference it from the rule onceThe audience changes often, or several rules share itOne extra object; you publish the group, not the rule

Recommendation: use B when the audience churns or is shared (it isolates membership changes from the rule and pairs with partial publish). Use A for a small, stable, rule-specific set.


Approach A: directly on the rule

Add and remove users and groups in the rule scope. Deltas leave everyone else in scope untouched:

curl -sS -X PATCH "$PB_API_BASE/policy/security/rules/$RULE_ID" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope": {
"users": {
"addUsers": ["0UR01CAROLXXXXXXXXXXXXXXXXXXX"],
"removeUsers": ["0UR01BOBXXXXXXXXXXXXXXXXXXXXX"],
"addUserGroups": ["0UG01ENGXXXXXXXXXXXXXXXXXXXXX"]
}
}
}'

Response (200):

{ "id": "0RLEXAMPLERULEXXXXXXXXXXXXXX" }
note

To scope a rule to everyone, send "users": { "isAny": true }. To go back to a specific list, send the add… fields with isAny omitted or false.


Approach B: via a local user group

1. Create (or reuse) a local user group

curl -sS -X POST "$PB_API_BASE/user-groups" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "DevTools block - scope", "userIds": ["0UR01ALICEXXXXXXXXXXXXXXXXXXX"] }'
{ "id": "0UG01SCOPEXXXXXXXXXXXXXXXXXXX" }
export UG_ID='0UG01SCOPEXXXXXXXXXXXXXXXXXXX'

2. Reference the group from the rule (once)

curl -sS -X PATCH "$PB_API_BASE/policy/security/rules/$RULE_ID" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "scope": { "users": { "addUserGroups": ["'"$UG_ID"'"] } } }'

Response (200):

{ "id": "0RLEXAMPLERULEXXXXXXXXXXXXXX" }

3. From now on, edit the group, not the rule

curl -sS -X PUT "$PB_API_BASE/user-groups/$UG_ID" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "users": [ { "userId": "0UR01DANXXXXXXXXXXXXXXXXXXXXX", "action": "add" } ] }'

Response (200):

{ "id": "0UG01SCOPEXXXXXXXXXXXXXXXXXXX", "userGroupId": "0UG01SCOPEXXXXXXXXXXXXXXXXXXX" }

The rule stays put; only the group changes. Publish the group (with partial publish, publish only 0UG...).

note

This is the foundation of a gradual rollout: keep adding members to the group over time and the rule's reach expands with each publish.


Verify and publish

curl -sS "$PB_API_BASE/policy/security/rules/$RULE_ID" -H "Authorization: Bearer $PB_TOKEN"

curl -sS -X POST "$PB_API_BASE/configuration-management/draft/publish" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"description": "Update rule audience"}'

The GET returns the full rule so you can confirm the scope:

{
"id": "0RLEXAMPLERULEXXXXXXXXXXXXXX",
"name": "Block developer tools",
"scope": {
"users": {
"isAny": false,
"userGroups": [ { "id": "0UG01SCOPEXXXXXXXXXXXXXXXXXXX", "name": "DevTools block - scope" } ]
}
// ... other scope segments
}
// ... controls, metadata
}

The publish returns 201 when a new active version is created.


Full script (Python, approach B)

import os, requests

base = os.environ["PB_API_BASE"]
headers = {"Authorization": f"Bearer {os.environ['PB_TOKEN']}"}
rule_id = os.environ["RULE_ID"]

# 1. Create a local user group
ug_id = requests.post(f"{base}/user-groups", headers=headers,
json={"name": "DevTools block - scope", "userIds": ["0UR01ALICEXXXXXXXXXXXXXXXXXXX"]},
timeout=30).json()["id"]

# 2. Reference it from the rule (once)
requests.patch(f"{base}/policy/security/rules/{rule_id}", headers=headers,
json={"scope": {"users": {"addUserGroups": [ug_id]}}}, timeout=30).raise_for_status()

# 3. Ongoing: change membership on the group
def set_members(add=(), remove=()):
users = [{"userId": u, "action": "add"} for u in add] + \
[{"userId": u, "action": "remove"} for u in remove]
if users:
requests.put(f"{base}/user-groups/{ug_id}", headers=headers,
json={"users": users}, timeout=30).raise_for_status()

set_members(add=["0UR01DANXXXXXXXXXXXXXXXXXXXXX"])

# 4. Publish only the group
requests.post(f"{base}/configuration-management/draft/partial-publish", headers=headers,
json={"entityIds": [ug_id], "description": "Expand rule audience"}, timeout=30)