zynactradocs

Org rules

Narrow the product's policy for one client, without changing the product or adding code.

Sooner or later one client asks for a rule of its own: "only the executive sees executive salaries", "leave for the board is approved outside the system". Adding if orgId == "acme" to code, or a condition every client gets, are both wrong. An org rule is the right tool: a deny that applies to one org only, compiled into a Cerbos scoped policy.

access/orgs/org_acme.yaml
org: org_acme
rules:
  executive_salaries:
    description: Salaries in the executive unit are visible only to the person themselves.
    deny: [employee:read:salary]
    when: R.attr.orgUnitId == "exec" && R.attr.ownerId != P.id

List the files in zaccess.yaml (a glob may match nothing):

zaccess.yaml
orgRules: [./access/orgs/*.yaml]

What they can do

  • Only deny. An org rule can't grant anything, whatever its condition says. The generated scoped policy only takes access away.
  • Only product permissions. access.* can't be narrowed, so administration works the same in every org.
  • Only required attributes in when, with the same variables as action conditions. A missing optional value would make the condition fail, which would skip the deny.

Where they apply

Everywhere a decision is made: record checks, list filters (the rule's negation joins the WHERE clause), and Explain, which names the rule with its description. Nothing in the product's code changes: the SDKs send the org as the Cerbos scope for kinds that org has rules for.

How they're built

zaccess gen compiles each org and kind with rules into policies/orgs/<org>/<kind>.yaml, a resource policy with scope: <org> that requires the product policy's allow as well (SCOPE_PERMISSIONS_REQUIRE_PARENTAL_CONSENT_FOR_ALLOWS). If that file is missing from what Cerbos serves, every check of that kind in that org is denied; leave lenientScopeSearch off so it never falls back to the product policy.

Testing them

Policy tests set scope: <org> on the resources:

resources:
  exec_salary:
    id: e_1
    kind: employee
    scope: org_acme            # the SDKs send this for orgs with rules
    attr: { orgId: org_acme, ownerId: u_exec, ownerPath: /u_ceo/u_exec/, orgUnitId: exec }

conformance/policy-tests/org_rules_test.yaml in zynactra/access is a complete suite.

Cover the denied case, the case the rule leaves alone (the person themselves), and the same record in another org, where the rule must not apply.

Org rules change by deploy, like every policy. Rules that clients edit themselves are not supported.

Edit on GitHub

On this page