Skip to content
Ironflow is pre-1.0: APIs can change between releases. Pin a version. What is ready →

Roll out a policy set with monitor mode

A new policy set starts in monitor mode. In this mode the set runs on every request, and it blocks none of them. Ironflow records what the set would have denied. You read the records, fix the rules, and then switch to enforce.

This guide needs spec.auth.policyEnforcement: true on the server. Without it, no request meets the set. ironflow policy pull prints a warning when enforcement is off.

Terminal window
ironflow policy push ./policies

When the organization has no set, the first push is in monitor mode. To be explicit, add --mode monitor. In the dashboard, the Mode switch on the Policies page shows Monitor (record would-deny, block nothing).

Wait for enough traffic to cover your normal work: scheduled jobs, deploys, the work of each team. The longer the window, the fewer surprises.

Each decision that the set would have denied becomes an audit row with the event type authz.decision.would_deny. List them with the audit API:

Terminal window
curl -s -H "Authorization: Bearer $IRONFLOW_API_KEY" \
"http://localhost:9123/api/v1/audit?event_type=authz.decision.would_deny&limit=100"

In the dashboard, open Audit Log and filter by the event type. The payload of a row has these fields:

FieldMeaning
action, resourceWhat the caller tried.
api_key_id, user_idWho tried it.
reasonThe sorted reasons of the set, joined with ; . For an error, policy evaluation error (<class>).
policy_set_versionThe version of the set that decided.
policy_set_modemonitor.
method, pathThe HTTP request. Present for gate checks.
environmentThe environment of the request.

The row is stored in the environment of the request. A row from env_prod does not show in a view of env_default. Query each environment that matters.

The capture settings for allowed decisions do not apply to would_deny rows. Ironflow samples these rows, as the next section says.

A broad rule can match every request. To protect the audit store, Ironflow writes at most one row for each combination of organization, action and first reason, every 10 seconds on each node. The counter is exact. It counts every would-deny decision.

A request whose would_deny row is sampled out writes an allowed row, as it would with no set. The capture settings for allowed decisions apply to that row.

Handler-side checks (for example the impersonation check) write their own would_deny rows too, with the same sampling.

The row count is not the request count. Use the row list to find which rules fire and for whom. Use the metric to count.

ironflow_policy_would_deny_total{org="org_acme"}

This counter goes up for every request that a monitor set would have denied. It includes evaluation errors, timeouts and compile failures. A set in enforce mode counts its denies in ironflow_policy_set_denies_total{org}.

Also watch ironflow_policy_set_compile_failed{org}. A value of 1 means the stored set does not compile on that node. A set in monitor mode that does not compile blocks nothing, but it also checks nothing.

For each reason in the rows, decide: is the deny correct, or is the rule too broad? Change the files. Run opa test. Dry-run an input from a row:

Terminal window
ironflow policy dry-run ./policies --input request.json

Push again. The mode stays monitor, because you did not pass --mode. See Debug a deny for the reasons and the error classes.

When the rows show only denies that you want, switch:

Terminal window
ironflow policy push ./policies --mode enforce

The write runs the same checks as any write. The version number goes up, and the audit row of the change records the new mode.

In the dashboard, choose Enforce in the Mode switch. A dialog shows the count of would-deny decisions of the last 24 hours in the current environment, with a link to the filtered audit view. The count comes from sampled rows. It is a guide, not an exact total.

If enforcement blocks something that it must not block, switch back first and investigate after:

Terminal window
ironflow policy push ./policies --mode monitor

Or use the Mode switch in the dashboard. If your own policy blocks policy writes for all admins, you cannot push. Use the operator break-glass. See Recover from a lockout.

A rollback keeps the current mode. To undo a rule change and the mode, roll back and then push the mode you want. See Author a policy set.