> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/governance/sod/sod-policies-and-rule-sets/create-an-sod-policy.md).

# Create an SoD policy

Build a segregation-of-duties policy by hand — segments, thresholds, exceptions and the manager group — and test both directions before you activate it.

## What this is, and when you need it

A hand-built `SOD_POLICY` is how you express a conflict that no shipped rule set covers: your own business process, your own entitlement names, and duties that often live in two different applications. You will do this before you do anything else with SoD, because one policy taken all the way through — defined, detected, remediated, proved quiet — is what tells you whether the rest of the programme is worth starting.

The mechanics you are configuring, and the reason severity is not the switch it looks like, are on [SoD policies and rule sets](/administration-guide/governance/sod/sod-policies-and-rule-sets.md).

## At a glance

|                          |                                                                                                                                                                                         |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **You will end up with** | One active `SOD_POLICY` with two segments, detecting every user who holds both sides of one named conflict                                                                              |
| **Where**                | **Access Control → Segregation of Duties → Policies** (`/webconsole/segregation-of-duties`); editing is `/webconsole/sod-policy-edit?id=<SOD_POLICY_ID>`                                |
| **You need first**       | The named entitlements that confer each duty; a group to own the policy; a disposable test user you can grant both sides to                                                             |
| **Takes**                | 20 to 40 minutes for the policy, plus one detection cycle before you trust it                                                                                                           |
| **Reversible**           | Yes — clear **Active** on the policy and enforcement stops immediately. Nothing about the policy is destructive; the access it *causes you to revoke* is a separate, non-reversible act |

## Before you begin

Decide the shape first, because it changes what you type into every threshold field. There are two correct ways to express a classic two-role conflict and they are not interchangeable.

| Shape            | Segments                                                               | Segment threshold | Policy threshold | Use when                                                                    |
| ---------------- | ---------------------------------------------------------------------- | ----------------- | ---------------- | --------------------------------------------------------------------------- |
| **One segment**  | A single segment holding both `Payment Creator` and `Payment Approver` | **2**             | **1**            | Each side is exactly one entitlement and always will be                     |
| **Two segments** | Segment A: payment initiation roles. Segment B: payment approval roles | **1** each        | **2**            | Either side has, or will plausibly acquire, several equivalent entitlements |

The two-segment shape is the one that scales. It says "at least one initiator permission **and** at least one approver permission", so adding a fourth equivalent approval role next year is one line in segment B rather than a rethink of the arithmetic. The steps below assume it.

You also need the roles, groups, resources or organizations that actually represent the conflicting duties, a group to own the policy (`SOD_POLICY.MANAGER_GROUP_ID` is who gets notified on a violation), and the three `SOD_RISK` metadata types present — they are seeded, and [SoD rule and policy reference](/administration-guide/reference/sod-rules-and-rule-sets.md) lists them. Read [Change configuration safely](/administration-guide/start/change-safely.md); save the policy **inactive** first, because an active `HARD` policy blocks provisioning the moment it exists.

## Build the policy

{% stepper %}
{% step %}

### Write the truth table before you open the screen

For each test user, list three columns: the entitlements they hold that this policy matches, which segments those matches violate, and the policy result you expect. Configure to that table, then test against it. A policy you cannot write a truth table for is a policy whose thresholds are guesses.

| Test user          | Matched entitlements                                       | Violated segments | Expected policy result                            |
| ------------------ | ---------------------------------------------------------- | ----------------- | ------------------------------------------------- |
| Compliant clerk    | `PO_CREATOR`                                               | A                 | **No violation** — 1 of 2 segments                |
| Compliant approver | `PO_APPROVER`                                              | B                 | **No violation** — 1 of 2 segments                |
| Direct conflict    | `PO_CREATOR`, `PO_APPROVER`                                | A and B           | **Violation** — 2 of 2 segments                   |
| Inherited conflict | `PO_CREATOR` direct, `PO_APPROVER` through a business role | A and B           | **Violation**, reported as indirect on the B side |
| Neither            | —                                                          | none              | **No violation**                                  |
| {% endstep %}      |                                                            |                   |                                                   |

{% step %}

### Create the policy inactive

**Access Control → Segregation of Duties → Policies → New policy**. On **General Information** set **Name**, **Severity**, **Threshold**, **Risk**, **Manager Group** — and leave **Active** off.

**Threshold** is `POLICY_THRESHOLD`: how many segments a user must trigger before this is a violation. For a classic two-sided conflict, **2**. It defaults to **1**, which with two segments means *either* side alone is a violation — almost never what you want.
{% endstep %}

{% step %}

### Add one segment per duty

On **Segments Configuration**, add a segment per side of the conflict. Each has its own **Threshold** (`SEGMENT_THRESHOLD`, how many of that segment's entitlements the user must hold for the segment to count) and four entitlement pickers: **Roles**, **Groups**, **Resources**, **Organizations**.

Set each segment's threshold to **1** for the two-segment shape: three interchangeable transactions in one segment then means "any one of these three".

Do not put unrelated conflicts in one segment. A segment is one side of one conflict; two conflicts are two policies.

{% hint style="warning" %}
**Do not use threshold 1 for a two-role conflict.** A single segment holding `Payment Creator` and `Payment Approver` with `SEGMENT_THRESHOLD = 1` is violated by holding *either* role, so every payment clerk and every payment approver in the organisation becomes a violator. The mirror-image mistake is `POLICY_THRESHOLD = 1` across two segments, which does the same thing one level up — and 1 is the shipped default for `POLICY_THRESHOLD`, so this is the error you get by not deciding. In both cases the symptom is identical: the violation count is roughly the size of the population holding *any* of the entitlements. The fix is to raise whichever threshold expresses the **combination**.

The opposite error is a threshold that can never be met — a segment threshold higher than the number of entitlements in the segment. The Segments Configuration screen shows a warning icon on a segment in that state, and a segment in that state silently never triggers, so the policy reports nothing and looks healthy.
{% endhint %}
{% endstep %}

{% step %}

### Decide exceptions and manager handling

**Exceptions Allowed** (`EXCEPTIONS_ALLOWED`) controls whether a `SOD_EXEMPTION` may be recorded against this policy at all — with it off, the Violations screen answers `Exemptions are not allowed for this policy`. **Allow managers to handle violations** (`MANAGER_CAN_HANDLE_SPV`) lets the manager group act on violations instead of only being notified.
{% endstep %}

{% step %}

### Test both directions, then activate

With the policy still inactive, work your truth table on disposable users. Give one user each side alone and confirm no violation; give one both and confirm the conflict is detected; give one an *inherited* side through a business role and confirm it is detected identically. Only then set **Active**.

If severity is `HARD`, the activating save is the moment provisioning starts refusing conflicting grants for the whole population — including grants already in flight.
{% endstep %}
{% endstepper %}

## Variant: when the two duties live in different applications

The two duties in a real conflict often live in different applications: vendor master maintenance in a procurement platform, payment release in SAP. A hand-built policy handles that directly, because a segment's entitlement pickers are not scoped to one managed system. One segment can hold the role that represents procurement access, and the segment beside it can hold the role that represents the SAP payment transaction. Four extra things apply.

**Get both sides into the access model first.** Synchronize and correlate identities and effective access from **both** managed systems, so that the person holding both grants is one OpenIAM user rather than two unlinked accounts. A cross-application policy evaluated against half-correlated data reports nothing at all, and reports it convincingly. See [Set up a synchronization](/administration-guide/lifecycle/synchronize-and-import-data.md).

**One segment per business function, not per application.** Create a segment for **maintain vendor master** and a segment for **release payment**. Resist making the segments "procurement access" and "SAP access": access to an application is not a duty, and a policy built that way flags everybody who happens to use both systems.

**Test the inherited path on both sides.** Four disposable users: one with each side alone, one with both directly, and one who inherits one side through a business role. Then run detection across the population and reconcile the count against your truth table.

**Establish joint ownership before you go hard.** A cross-application conflict has two application teams and usually one process owner, and remediation always lands on somebody who did not write the policy. Run it `SOFT` until both teams have agreed, in writing, who removes what. A `HARD` cross-application policy makes one team's provisioning fail because of the other team's data.

{% hint style="info" %}
**A rule set's single target managed system does not make rule-set content single-application.** The **Target managed system** you choose at activation scopes name *resolution* — which existing entitlements a rule's names match against, and where missing ones are created. The `SOD_POLICY` rows it generates are ordinary policies with no system affinity whatsoever, so you can open one afterwards and add a segment entitlement belonging to a different managed system. For a conflict that spans systems from the outset, build the policy by hand as above, or author a custom rule set and resolve every reference explicitly in the activation dialog.
{% endhint %}

## Verification

| What you did                           | Evidence                                                                                                             |
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Created or updated the policy          | `CREATE_SOD_POLICY` / `UPDATE_SOD_POLICY` audit action; the `SOD_POLICY` row and its `SOD_POLICY_SEGMENT` children   |
| Deleted a policy                       | `DELETE_SOD_POLICY`                                                                                                  |
| The thresholds express the combination | Your compliant single-side test users are absent from the Violations tab and the both-sides user is present          |
| An inherited side is caught            | The inherited-conflict test user appears with the drill-down showing an `INDIRECT[...]` contribution on that segment |
| A `HARD` policy blocks                 | The negative test fails with `SOD_POLICY_VIOLATION` and leaves a `HARD_SOD_POLICY_VIOLATION_DETECTION` audit entry   |

## When it goes wrong

| Symptom                                                                   | Cause                                                                                                                                                                                                                                                                       | Fix                                                                                                                                                                                                 |
| ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Every user with one side of the conflict is in violation                  | `SOD_POLICY.POLICY_THRESHOLD` is `1`, its default                                                                                                                                                                                                                           | Set it to the number of segments that must be triggered                                                                                                                                             |
| A segment never triggers                                                  | `SEGMENT_THRESHOLD` is higher than the number of entitlements the user could plausibly hold, or the segment is `ACTIVE = 'N'`                                                                                                                                               | Check both on `SOD_POLICY_SEGMENT`; the screen shows a warning icon on an unsatisfiable segment                                                                                                     |
| A cross-application policy detects nothing at all                         | The two accounts were never correlated to one OpenIAM user                                                                                                                                                                                                                  | Correlate first; the policy is evaluating two half-users, each holding one side                                                                                                                     |
| The inherited test user is not detected                                   | The authorization graph is stale, so indirect contributions are missing                                                                                                                                                                                                     | Rebuild it — see [Search indexes and the authorization graph](/administration-guide/reference/search-indexes.md)                                                                                    |
| Severity you set by hand reverted to `SOFT`                               | The policy came from a rule set, and `Enforce` re-derives severity from the risk tag                                                                                                                                                                                        | Change the rule's `riskLevel`, not the policy's severity — see [SoD policies and rule sets](/administration-guide/governance/sod/sod-policies-and-rule-sets.md#the-severity-override-on-activation) |
| Provisioning suddenly fails across the population                         | The policy went active with `SEVERITY = HARD` while conflicts were outstanding                                                                                                                                                                                              | Look for `HARD_SOD_POLICY_VIOLATION_DETECTION` entries; clear **Active** or set `SEVERITY = 'SOFT'` to unblock while you remediate                                                                  |
| A conflicting grant went through although the policy is active and `HARD` | Whatever performed the grant suppressed the check: setting `skipSodPolicyCheck = true` on a provisioning call bypasses **both** `SOFT` and `HARD` evaluation entirely, and no audit entry is written, so the absence of a violation record is not proof no conflict existed | Find what granted it — a synchronization script, a custom workflow or an integration — and remove the flag. Until you do, treat that path as unenforced in your control test record                 |

## Roll it back

Clear **Active** on the `SOD_POLICY` row. Enforcement stops immediately, the policy and its segments survive, and the violation index drops the policy's entries on the next detection run. Setting `SEVERITY = 'SOFT'` instead keeps detection running while unblocking provisioning — but if the policy was generated by a rule set, remember the next `Enforce` will undo that edit.

## Related

* [SoD policies and rule sets](/administration-guide/governance/sod/sod-policies-and-rule-sets.md) — the model, the enforcement ladder and the severity override
* [SoD detection and violations](/administration-guide/governance/sod/sod-detection-and-violations.md) — running the population sweep that finds who already holds the conflict
* [Activate an SoD rule set](/administration-guide/governance/sod/sod-policies-and-rule-sets/activate-an-sod-rule-set.md) — the other way policies come into existence
* [SoD rule and policy reference](/administration-guide/reference/sod-rules-and-rule-sets.md) — every value and every table behind these screens

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/governance/sod/sod-policies-and-rule-sets/create-an-sod-policy.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
