Skip to content

Managed Initiative on a Management Group

Standard change: Assign a managed policy initiative to a management group

Effect: a built-in or platform-managed initiative is assigned at a management group, and every subscription below it inherits the initiative.

Scope boundary. Assigning an initiative on a single spoke is the workload team's responsibility, not a standard change. If you do it in this repository, use the 02_subscriptions folder (Policy assignments).

Request fields

Field Use
Policy definition/initiative Name Built-in name or GUID, or the custom initiative name
Rationale pull request; properties.description
Scope Target management group, for example cloudplatform-landingzones-corp
Comments parameters, enforcement mode

The initiatives the platform already assigns

These are hard-coded in infra/deploy/postdeployment/main.tf (module "landing_zone_policies") and assigned at the cloudplatform management group. Every platform environment gets them.

Assignment display name Initiative
Platform Default - Compliance - ISO 27001:2013 built-in 89c6cddc-1c73-4ac1-b19c-54d1a15a42f2
Platform Default - Compliance - CIS 1.4.0 built-in c3f5c4d9-9a1d-4a99-85c0-7f93e384d5c5
Platform Default - Compliance - CIS 3.0.0 built-in 470a962c-86a0-433b-803a-3c176b5ce79c
Platform Default - Compliance - ASC built-in 1f3afdf9-d0c9-4c3d-847f-89da613e70a8 (Microsoft cloud security benchmark)
Platform Default - Compliance - NIS2 built-in 32ff9e30-4725-4ca7-ba3a-904a7721ee87
Platform Default - Diagnostic Settings - v2 - <region> built-in 0884adba-2312-4468-abeb-5422caed1038, one per active region
Xebia Default - Defender for Cloud v2 - Landing Zones only when enable_defender_for_cloud_for_spokes = true; scoped to landingzones

There is no tfvars switch to remove the five compliance initiatives. Changing them is a code change. The exemptions the platform applies to them are documented in docs/policy_exemptions/current-platform-exemptions.md and in ADR-0001 to ADR-0005 and ADR-0013.

Assign another initiative to a management group

1. Get the initiative ID

  • Built-in: Azure portal → Policy → Definitions → filter Initiative → open it → copy the Definition ID, for example /providers/Microsoft.Authorization/policySetDefinitions/06f19060-9e68-4070-92ca-f15cc126059e.
  • Custom (platform-managed): see Add a custom definition or initiative. Its ID is /providers/Microsoft.Management/managementGroups/<cloudplatform id>/providers/Microsoft.Authorization/policySetDefinitions/<name>.

2. Create the assignment file

Create <env-folder>/policies/policy_assignments/01_management_groups/<name>.json, using the format in Policy assignments:

{
  "name": "cis-v2-corp",
  "policy_definition_id": "/providers/Microsoft.Authorization/policySetDefinitions/06f19060-9e68-4070-92ca-f15cc126059e",
  "enforce": true,
  "identityType": "SystemAssigned",
  "location": "westeurope",
  "notScopes": null,
  "managementGroupId": "/providers/Microsoft.Management/managementGroups/cloudplatform-landingzones-corp",
  "non_compliance_message": null,
  "properties": {
    "displayName": "CIS Microsoft Azure Foundations Benchmark v2.0.0 - Corp",
    "description": "Change <ticket>",
    "metadata": { "assignedBy": "Infrastructure as Code (IaC)" },
    "parameters": null
  }
}

The sample configuration contains two complete, disabled examples (.json.ignore) of this pattern, with all parameters spelled out: CIS v2.0.0 and the Microsoft cloud security benchmark, both under config/Demo/canary/policies/policy_assignments/01_management_groups/.

3. Deploy

Run hub.

  • Expected postdeployment plan (primary region): + the management group policy assignment.
  • With an identity: + role assignments.
  • With automatically_start_policy_remediation = true: + one remediation per initiative member.

Add a custom definition or initiative

Custom definitions and initiatives are deployed by the foundation layer (primary region only) at the cloudplatform management group. The folders are set in <env-folder>/<primary region>/foundation.auto.tfvars:

policy_definition_json_file_relative_path     = "policies/policy_definitions"
policy_definition_json_file_pattern           = "/**/*.json"
policy_set_definition_json_file_relative_path = "policies/policy_set_definitions"
policy_set_definition_json_file_pattern       = "/**/*.json"

The file format is the Azure export format: name plus properties.{policyType, mode, displayName, description, metadata, parameters, policyRule} for a definition, and properties.{policyType, parameters, metadata, policyDefinitions[], policyDefinitionGroups[]} for an initiative. In an initiative you can write ${root_scope_resource_id} in a policyDefinitionId; it is replaced with the cloudplatform management group ID (infra/modules/policy/main.tf).

The initiative's display name in Azure is its name. display_name = each.value.name in infra/modules/policy/main.tf, so properties.displayName is not used for initiatives.

Definitions and assignments can go in the same pull request: foundation runs before postdeployment in one hub run.

Verify

Azure portal → Policy → Assignments → scope = the management group. The assignment is listed, and Compliance starts filling in after the first evaluation.

Roll back

Delete the assignment file (and the definition files, if they were added for this change), then run hub.