← IAM Ideas
IAM Ideas 2026-06-29

Iiq Role Profile Integrity Checker

Detects stale entitlement references in IIQ role profiles — before they cause provisioning failures, silent certification errors, or degraded role scoring — for IAM engineers managing 500+ connectors.

Iiq Role Profile Integrity Checker

IIQ Role Profile Integrity Checker

Detects stale entitlement references in IIQ role profiles — before they cause provisioning failures, silent certification errors, or degraded role scoring — for IAM engineers managing 500+ connectors.

Date: 2026-06-29 Type: Utility Theme: Protect + Detect Platform: SailPoint IdentityIQ Status: Idea

What it is

A Python utility that connects to the IdentityIQ REST API, retrieves all Bundle (role) definitions and their Application Profiles, then cross-references each profile's entitlement constraints against the live ManagedAttribute catalog. It reports every stale reference — entitlements cited in role profiles that no longer exist as managed attributes — grouped by application, severity-ranked, with a concrete remediation checklist. The utility is read-only: it fetches and reports; it never modifies IIQ objects.

Who it serves

IAM engineers and role administrators at organisations running IIQ with dozens to hundreds of IT Roles spanning 500+ connector applications. Most useful before a major aggregation refresh, a connector retirement, or the opening of a quarterly role certification campaign, where stale profile references silently corrupt what certifiers see.

The IIQ pain it addresses

When a managed attribute is deleted from IIQ (e.g., a role or group is removed from an application's aggregated entitlement catalog), the corresponding row in spt_bundle_profile_relation is not automatically removed — confirmed in IIQ 8.4 by the SailPoint Developer Community. The orphaned reference remains inside the Bundle's Profile indefinitely, causing:

  • Provisioning failures: IIQ attempts to provision a non-existent entitlement, generating ProvisioningTransaction errors that surface as connector-level noise — individually small, cumulatively misleading in log analysis.
  • Broken certifications: Certifiers see entitlement display names that resolve to [Unknown] or empty strings. At scale this drives rubber-stamping because certifiers stop trusting what they're reviewing.
  • Degraded role scoring: Role correlation and risk scoring degrade because the Bundle's expected entitlements cannot be matched to live Links, producing artificially low role coverage percentages.

At 500+ connectors, even a 0.1% entitlement churn rate per aggregation cycle generates dozens of stale bundle constraints over a single quarter. IIQ has no native alert or integrity scan for this condition — the problem accumulates silently with no dashboard indicator.

How it works

  1. Connect — reads sample-config.json for the IIQ base URL and service-account username. Password is sourced exclusively from the environment variable named in config["password_env"].
  2. Fetch Bundles — paginates GET /identityiq/rest/bundles to retrieve all IT Role and Business Role Bundle objects, extracting each Bundle's profiles[] array (Application name + entitlement constraint triples: attributeName + value).
  3. Fetch ManagedAttributes — for each unique Application referenced across all profiles, paginates GET /identityiq/rest/managedAttributes?applicationName=<app> to build an in-memory lookup of live (application, attributeName, value) triples.
  4. Cross-reference — for each profile constraint in each Bundle, checks whether the (application, attributeName, value) triple exists in the live managed-attribute lookup. Misses are flagged STALE.
  5. Score and rank — computes per-Bundle severity: HIGH if >50% of constraints are stale, MEDIUM if 10–50%, LOW if <10%.
  6. Report — prints a structured findings table to stdout (summary totals, affected Bundles ranked by severity, per-constraint detail) and writes role-integrity-findings.json for downstream tooling or ticketing unless --dry-run is passed.

What's in this folder

  • README.md — this file
  • requirements.md — functional, non-functional, and security requirements
  • script.py — Python 3.10+ utility; one third-party dependency (requests)
  • sample-config.json — illustrative configuration (.invalid TLD server URLs, no real credentials)
  • sample-output.txt — annotated stdout from a sample run against a synthetic 87-role, 12-application IIQ environment

How to run / read it

export IIQ_SERVICE_PASSWORD="<service account password>"
python3 script.py --config sample-config.json

Pass --dry-run to print findings to stdout without writing role-integrity-findings.json. Install the one required dependency first:

pip install "requests>=2.31"

Read sample-output.txt to see exactly what the utility prints for a deployment with 8 affected bundles and 15 stale constraints across SAP, Active Directory, Salesforce, ServiceNow, GitHub, and AWS connectors.

Estimated impact

At a 500-connector IIQ deployment with quarterly connector refresh cycles, accumulated stale bundle constraints typically number in the dozens. Each stale constraint produces one provisioning error or one [Unknown] certifier display per campaign. At 50 certifiers reviewing 3 campaigns per year, that is 150+ avoidable support tickets annually from a problem that takes under 2 minutes to detect. Scheduling this utility as a pre-campaign gate — via OS cron or IIQ's native Run Rule task invocation mechanism — converts a month-long post-mortem into a 2-minute fix list delivered before the campaign opens.

Why this fits an IIQ shop with 500+ connectors

At scale, entitlements churn continuously. Connectors are reconfigured, application schemas evolve during platform upgrades, managed attributes are renamed or removed when an application decommissions a role, and occasional hard-deletes via the IIQ admin console leave no downstream cleanup signal. The spt_bundle_profile_relation accumulation is invisible to standard IIQ dashboards and reports — it does not surface in the System Dashboard, the Role Management UI, or any out-of-box report. An organisation managing SAP ECC, Active Directory, ServiceNow, Workday, Salesforce, and 490+ additional applications will experience entitlement churn in multiple connectors every sprint cycle. The larger the estate, the more stale references accumulate. This utility runs as a scheduled pre-campaign gate, not a one-time remediation, because the problem regenerates continuously.

Sources

Requirements

Requirements — IIQ Role Profile Integrity Checker

Functional

  1. Connect to SailPoint IdentityIQ 8.x REST API using HTTP Basic auth over HTTPS.
  2. Retrieve all Bundle objects whose type matches the configured role_types list (default: ["IT Role", "Business Role"]) via paginated GET /identityiq/rest/bundles.
  3. For each Bundle, extract its profiles[] — each Profile references an Application name and a list of entitlement constraints (attributeName + value pairs representing spt_bundle_profile_relation entries).
  4. For each unique Application referenced across all profiles, retrieve the complete live ManagedAttribute catalog via paginated GET /identityiq/rest/managedAttributes?applicationName=<name>.
  5. Cross-reference every profile constraint against the live ManagedAttribute catalog. A constraint is STALE when no ManagedAttribute with matching application, attributeName, and value exists.
  6. Compute per-Bundle severity:
    • HIGH — more than 50% of profile constraints are stale
    • MEDIUM — 10% to 50% (inclusive) of constraints are stale
    • LOW — more than 0% but fewer than 10% of constraints are stale
    • CLEAN — zero stale constraints (not included in findings)
  7. Emit a structured findings report to stdout:
    • Summary header: total Bundles scanned, total with findings, total stale constraints
    • Table of affected Bundles sorted by severity (HIGH first) then alphabetically by name
    • Per-Bundle detail: Application name, stale attributeName, stale value, percentage stale
    • Remediation checklist at the end
  8. Write role-integrity-findings.json to the working directory on exit unless --dry-run is passed.
  9. Exit codes:
    • 0 — no stale constraints found
    • 1 — stale constraints detected
    • 2 — fatal error (connection, auth, configuration)

Non-Functional

  • Runtime: Python 3.10 or later. One third-party dependency: requests (HTTP client). No other pip packages.
  • Pagination: All list endpoints are paginated using limit and start query parameters. Default page size: 250. Adjust via config["page_size"].
  • Timeout: All HTTP calls time out after config["timeout_seconds"] seconds (default: 30). Applies per-request, not for the entire run.
  • Performance: Must complete in under 3 minutes against a deployment with 1,000 roles and 500 applications, assuming 500ms average API response time.
  • Safety: Exclusively GET requests. Safe to run while IIQ is live.

Security

  • Password must be read from the environment variable named in config["password_env"]. No plaintext passwords in config files, CLI arguments, or log output.
  • verify_ssl: false is accepted for test environments only; the script emits a WARNING to stderr when SSL verification is disabled.
  • TLS 1.2+ enforced via the requests + system CA bundle default.
  • role-integrity-findings.json contains no identity PII — only Bundle names, Application names, attributeNames, and entitlement values (all visible to any IIQ admin via the Role Editor).
  • The IIQ_SERVICE_PASSWORD environment variable must not appear in any log line or output file.

Error Handling

  • 401 / 403 — print auth error with the HTTP status; exit code 2. No retry.
  • 404 — print endpoint-not-found with the URL; exit code 2. Indicates misconfigured iiq_base_url.
  • 429 / 5xx — retry once after a 5-second back-off; exit code 2 if the retry also fails.
  • ConnectionError / Timeout — print the error with the target URL; exit code 2.

Dependency Declaration

The script declares its only dependency at the top in a comment parseable by pip-based tooling:

# requires: requests>=2.31

Operational

  • Designed to run as a pre-campaign gate: schedule via OS cron, IIQ Run Rule task invocation, or a CI/CD pipeline step that blocks campaign creation if exit code is 1.
  • The JSON output (role-integrity-findings.json) is structured for downstream consumption by ticketing systems (ServiceNow, Jira) or monitoring pipelines (Splunk, Sentinel).
  • No state is persisted between runs; each invocation is a fresh point-in-time integrity snapshot.

More from IAM Ideas