Archigov · docs
  1. Docs
  2. Guides

Writing Rules

Turn a standard, policy, pattern or principle into a machine-checkable rule — choose the scope, match the right elements, assert on properties, evidence or decisions, and dry-run before a board adopts it.

#Start from the Statement

A rule makes an artefact's statement checkable. Write the statement first, for people; then ask which fact in the derived model or the imported evidence would show it is met. If no such fact exists, the artefact is still valuable without a rule — boards cite it, reviews link to it — it simply is not evaluated.

#Choose the Kind of Fact

The statement is about…UseExample
A property Archigov normalises (region, TLS, public access, tags)A property assertionProduction resources run in UK regions
A configuration Defender or Azure Policy already assessesAn evidence assertion (op: evidence)Storage accounts do not allow public blob access
Whether a decision exists for a kind of applicationhasDecisionApplications running Azure SQL have a data-store decision
Whether deployed resources match an accepted decisiondecisionConstraintDeployed databases are those the decision allowed
Ownership or sprawl at application levelhasOwnerTag, maxResourcesOfTypeEvery application has an owner

Important

Do not rebuild a security-posture check as a property rule when Defender or Azure Policy already assesses it. Assert on the imported evidence instead. Your rule then rests on the same result your cloud security team sees, and no evidence is reported as a finding rather than silently passing.

#Examples

#A Property Rule

Production resources must be in UK regions:

JSON
{
  "scope": "resource",
  "match": { "where": [ { "path": "tags.env", "op": "eq", "value": "prod" } ] },
  "assert": { "path": "location", "op": "in", "value": ["uksouth", "ukwest"] }
}

#An Evidence Rule

Storage accounts pass Defender's public-access assessment:

JSON
{
  "scope": "resource",
  "match": { "type": "Microsoft.Storage/storageAccounts" },
  "assert": { "op": "evidence", "source": "defender", "control": "storage-public-access", "state": "pass" }
}

Omit source to accept evidence from any source.

#A Decision Rule Pair

Applications running Azure SQL need an accepted data-store decision:

JSON
{ "scope": "application", "assert": { "op": "hasDecision", "topic": "data-store", "type": "Microsoft.Sql" } }

…and their databases must be the types that decision allows:

JSON
{
  "scope": "resource",
  "match": { "typeIn": ["Microsoft.Sql/servers", "Microsoft.DBforPostgreSQL/flexibleServers", "Microsoft.DocumentDB/databaseAccounts"] },
  "assert": { "op": "decisionConstraint", "topic": "data-store" }
}

The decision supplies the allowed types in its checkable constraint. When an application has no accepted decision on the topic, the constraint rule skips it — the hasDecision rule reports the gap instead.

#A Technology-radar Rule

Retired OS versions are a decision about technology, so a rule may read derived properties directly:

JSON
{
  "scope": "resource",
  "match": { "type": "Microsoft.Compute/virtualMachines" },
  "assert": { "path": "props.osSku", "op": "notIn", "value": ["2012-R2-Datacenter", "2012-Datacenter", "2008-R2-SP1"] }
}

#Critical Applications Only

Any rule can be narrowed by the application's criticality with app.* paths in match.where, at either scope. Critical applications need an accepted hosting decision:

JSON
{
  "scope": "application",
  "match": { "where": [ { "path": "app.criticality", "op": "eq", "value": "critical" } ] },
  "assert": { "op": "hasDecision", "topic": "hosting" }
}

An unclassified application does not match critical, so check the Business Services page for applications nobody has classified yet.

#Validate, Then Dry-run

In the artefact editor:

  1. Save the draft. The rule is validated: an unknown operator, a missing field or an invalid regular expression is reported in place.
  2. Dry run evaluates the draft rule against the current model and evidence without storing anything, and shows what it would find — its blast radius.
  3. Pre-review the artefact, then submit it. The board adopts it; only then is it evaluated in every run.

With Rule Drafting enabled, an author can generate a rule from the statement. The draft comes back already validated and dry-run, and the author decides whether to keep it.

#Severity and Enforcement

Findings carry the artefact's severity. Policies carry an enforcement level — mandatory or recommended — that tells boards how to treat exceptions. Neither changes how the rule is evaluated.

#Common Mistakes

  • Asserting on the wrong path. A rule sees name, type, location, tags.<key>, props.<key> and the owning application's classification as app.*. Prefer the normalised properties (props.publicAccess, props.minTlsVersion, props.httpsOnly, props.osSku) — raw ARM property names differ between resource types and API versions.
  • Forgetting the match. A resource rule without match applies to every resource.
  • Treating missing as safe. missing passes when the property is absent; prefer evidence when absence means unknown.

The full grammar is in the Rule DSL reference.