Skip to main content

Bulk-sync a rule's applications

A common automation job: keep the list of SaaS applications governed by an access-and-data rule in sync with an external source (a CMDB, a risk feed, a spreadsheet). This walkthrough does it with delta patch, so you never have to read-modify-write the whole list and never clobber concurrent edits.

Prerequisites: a Super User service account and the environment variables from Getting started. Read Delta patch and Draft and publish first.

The scenario: a rule currently scopes a set of SaaS applications. Your source of truth says some applications should be added and others removed. You will compute that delta and apply it in a single PATCH.


1. Identify the rule and the desired applications​

export RULE_ID='0RLEXAMPLERULEXXXXXXXXXXXXXX' # an access-and-data rule

You have a desired set of application IDs. You do not need to know the rule's current list: delta patch only needs what to add and what to remove.


2. (Optional) read the current list to compute a delta​

If your source gives you a full desired set rather than an explicit add/remove list, read the rule once, diff in your code, then send the delta. The current SaaS application IDs live at applications.saas.specific.applicationIds.

Python​

import os, requests

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

# Desired end state from your source of truth:
desired = {"0AP01AAA...", "0AP01BBB...", "0AP01DDD..."}

rule = requests.get(f"{base}/policy/access-and-data/rules/{rule_id}", headers=headers, timeout=30).json()
saas = rule.get("applications", {}).get("saas", {}).get("specific", {})
current = set(saas.get("applicationIds", []))

to_add = sorted(desired - current)
to_remove = sorted(current - desired)
print("add:", to_add, "remove:", to_remove)
note

Even though you read the current list here, you still send a delta, not a full replacement. That way, any application a concurrent editor added that is not part of your desired-set logic is left untouched if you choose to scope your diff narrowly. If your source truly owns the entire list, a full replacement (applicationIds) is also valid; see Delta patch: when to use which.


3. Apply the delta (PATCH the draft)​

Send only the additions and removals. Include accessMode: "specific" so the scope is in specific-applications mode.

curl -sS -X PATCH "$PB_API_BASE/policy/access-and-data/rules/$RULE_ID" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"applications": {
"saas": {
"accessMode": "specific",
"specific": {
"addApplicationIds": ["0AP01DDDXXXXXXXXXXXXXXXXXXXXX"],
"removeApplicationIds": ["0AP01CCCXXXXXXXXXXXXXXXXXXXXX"]
}
}
}
}'

A 200 means the draft was updated:

{ "id": "0RLEXAMPLERULEXXXXXXXXXXXXXX" }

4. Verify and publish​

Read the rule back from the draft to confirm the new list, then publish.

# verify (draft)
curl -sS "$PB_API_BASE/policy/access-and-data/rules/$RULE_ID" \
-H "Authorization: Bearer $PB_TOKEN"

# publish
curl -sS -X POST "$PB_API_BASE/configuration-management/draft/publish" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"description": "Sync access-and-data rule apps from source of truth"}'

The GET returns the full rule (confirm the application list), and the publish returns 201 when a new active version is created.


Why delta wins here​

  • No lost updates. If a colleague added an application between your read and write, your delta does not erase it.
  • Smaller payloads. You send a handful of IDs, not the entire (possibly hundreds-long) list.
  • Retry-safe. Re-running the same delta is a no-op: adding an existing application or removing an absent one does not error. So if your job fails after the PATCH but before publish, run it again.

Beyond applications​

The same add/remove pattern works for the rule's other lists. Combine them in one PATCH:

{
"applications": {
"saas": {
"accessMode": "specific",
"specific": {
"addApplicationIds": ["0AP01DDD..."],
"addUrls": ["https://newtool.example.com"],
"removeWebClassifications": ["SocialNetworking"]
}
}
}
}

See Delta patch for the full list of delta-capable fields.