- Repo Folder Structure
- Custom Policy Definitions Module
- Policy Initiative (Set Definitions) Module
- Policy Definition Assignment Module
- Policy Initiative Assignment Module
- Policy Exemption Module
- Achieving Continuous Compliance
- 📗Useful Resources
- Limitations
📦examples
├──📜assignments_mg.tf
├──📜backend.tf
├──📜data.tf
├──📜definitions.tf
├──📜exemptions.tf
├──📜initiatives.tf
├──📜variables.tf
📦modules
└──📂def_assignment
├──📜main.tf
├──📜outputs.tf
└──📜variables.tf
└──📂definition
├──📜main.tf
├──📜outputs.tf
└──📜variables.tf
└──📂exemption
├──📜main.tf
├──📜outputs.tf
└──📜variables.tf
└──📂initiative
├──📜main.tf
├──📜outputs.tf
└──📜variables.tf
└──📂set_assignment
├──📜main.tf
├──📜outputs.tf
└──📜variables.tf
📦policies
└──📂policy_category (e.g. General, should correspond to [var.policy_category])
└──📜policy_name.json (e.g. whitelist_regions, should correspond to [var.policy_name])
📦scripts
├──📂dsc_examples
├──📜build_guest_config_packages.ps1 (build and publish azure policy guest configuration packages)
└──📜convert_to_v2.ps1 (converts policies to version 2 of the repo library)
This module depends on populating var.policy_name
and var.policy_category
to correspond with the respective custom policy definition json
file found in the local library. You can also parse in other template files and data sources at runtime, see the definition module readme for examples and acceptable inputs.
module whitelist_regions {
source = "gettek/policy-as-code/azurerm//modules/definition"
version = "2.6.1"
policy_name = "whitelist_regions"
display_name = "Allow resources only in whitelisted regions"
policy_category = "General"
management_group_id = data.azurerm_management_group.org.id
}
Policy Initiatives are used to combine sets of definitions in order to simplify their assignment
module platform_baseline_initiative {
source = "gettek/policy-as-code/azurerm//modules/initiative"
version = "2.6.1"
initiative_name = "platform_baseline_initiative"
initiative_display_name = "[Platform]: Baseline Policy Set"
initiative_description = "Collection of policies representing the baseline platform requirements"
initiative_category = "General"
management_group_id = data.azurerm_management_group.org.id
member_definitions = [
module.whitelist_resources.definition,
module.whitelist_regions.definition
]
}
⚠️ Warning: If any twomember_definition_ids
contain the same parameters then they will be merged by this module (except for"effect"
when settingmerge_effects = false
) as seen here. In most cases this is beneficial but if unique values are required it may be best practice to set unique keys directly within your custom definition.json files such as[parameters('listOfResourceTypesAllowed_WhitelistResources')]
instead of[parameters('listOfResourceTypesAllowed')]
.
📘 Microsoft Docs: Azure Policy initiative definition structure
module org_mg_whitelist_regions {
source = "gettek/policy-as-code/azurerm//modules/def_assignment"
version = "2.6.1"
definition = module.whitelist_regions.definition
assignment_scope = data.azurerm_management_group.org.id
assignment_effect = "Deny"
assignment_parameters = {
"listOfRegionsAllowed" = [
"UK South",
"UK West",
"Global"
]
}
}
module org_mg_platform_diagnostics_initiative {
source = "gettek/policy-as-code/azurerm//modules/set_assignment"
version = "2.6.1"
initiative = module.platform_diagnostics_initiative.initiative
assignment_scope = data.azurerm_management_group.org.id
assignment_effect = "DeployIfNotExists"
skip_remediation = false
skip_role_assignment = false
remediation_scope = data.azurerm_subscription.current.id
resource_discovery_mode = "ReEvaluateCompliance"
assignment_parameters = {
workspaceId = data.azurerm_log_analytics_workspace.workspace.id
storageAccountId = data.azurerm_storage_account.sa.id
eventHubName = data.azurerm_eventhub_namespace.ehn.name
eventHubAuthorizationRuleId = data.azurerm_eventhub_namespace_authorization_rule.ehnar.id
metricsEnabled = "True"
logsEnabled = "True"
}
assignment_not_scopes = [
data.azurerm_management_group.team_a.id
]
non_compliance_messages = {
null = "The Default non-compliance message for all member definitions"
"DeployApplicationGatewayDiagnosticSetting" = "The non-compliance message for the deploy_application_gateway_diagnostic_setting definition"
}
}
Use the exemption module in favour of not_scopes
to create an auditable time-sensitive Policy exemption
module exemption_team_a_mg_deny_nic_public_ip {
source = "gettek/policy-as-code/azurerm//modules/exemption"
name = "Deny NIC Public IP Exemption"
display_name = "Exempted while testing"
description = "Allows NIC Public IPs for testing"
scope = data.azurerm_management_group.team_a.id
policy_assignment_id = module.team_a_mg_deny_nic_public_ip.id
exemption_category = "Waiver"
expires_on = "2023-05-25" # optional
# optional
metadata = {
requested_by = "Team A"
approved_by = "Mr Smith"
approved_date = "2021-11-30"
ticket_ref = "1923"
}
}
Azure Policy supports the following types of effect:
💡 Note: If you're managing tags, it's recommended to use
Modify
instead ofAppend
as Modify provides additional operation types and the ability to remediate existing resources. However, Append is recommended if you aren't able to create a managed identity or Modify doesn't yet support the alias for the resource property.
Role assignments and remediation tasks will be automatically created if the Policy Definition contains a list of Role Definitions. You can override these with explicit ones, as seen here, or specify skip_role_assignment=true
to omit creation. By default these will scope at the policy assignment but can be changed by setting role_assignment_scope
.
Unless you specify skip_remediation=true
, the *_assignment
modules will automatically create remediation tasks for policies containing effects of DeployIfNotExists
and Modify
. The task name is suffixed with a timestamp()
to ensure a new one gets created on each terraform apply
.
To trigger an on-demand compliance scan with terraform, set resource_discovery_mode=ReEvaluateCompliance
on *_assignment
modules, defaults to ExistingNonCompliant
.
💡 Note:
ReEvaluateCompliance
only applies to remediation at Subscription scope and below and will take longer depending on the size of your environment.
- Should be Defined as high up in the hierarchy as possible.
- Should be Assigned as low down in the hierarchy as possible.
assignment_not_scopes
such as child resource groups, individual resources or entire subscriptions, can be specified as enforcement exemptions.- Policy overrides RBAC so even Subscription owners fall under the same compliance enforcements assigned at a higher scope (unless assigned at subscription scope).
⚠️ Requirement: Ensure the deployment account has at least Resource Policy Contributor role at thedefinition_scope
andassignment_scope
. To successfully create Role-assignments (or group memberships) the same account may also require the User Access Administrator role at theassignment_scope
or preferably thedefinition_scope
to simplify workflows.
- GitHub Repo: Azure Built-In Policies and Samples
- GitHub Repo: Contribute to Community Policies
- GitHub Repo: AWESOME-Azure-Policy - a collection of awesome references
- Microsoft Docs: Azure Policy Home
- Microsoft Docs: List of Builtin Policies
- Microsoft Docs: Index of Azure Policy Samples
- Microsoft Docs: Design Azure Policy as Code workflows
- Microsoft Docs: Evaluate the impact of a new Azure Policy definition
- Microsoft Docs: Author policies for array properties on Azure resources
- Microsoft Docs: Azure Policy Regulatory Compliance (Benchmarks)
- Microsoft Docs: Azure Policy Exemption
- Microsoft Tutorial: Build policies to enforce compliance
- Microsoft Tutorial: Security Center - Working with security policies
- VSCode Marketplace: Azure Policy Extension
- AzAdvertizer: Release and change tracking on Azure Governance capabilities
- Azure Citadel: Creating Custom Policies
- Terraform Provider: azurerm_policy_definition
- Terraform Provider: azurerm_policy_set_definition
- Terraform Provider: multiple assignment resources: azurerm_*_policy_assignment
- Terraform Provider: multiple remediation resources: azurerm_*_policy_remediation
- Terraform Provider: multiple exemption resources: azurerm_*_policy_exemption
DefinitionName
has a maximum length of 64 characters andAssignmentName
a maximum length of 24 charactersDisplayName
has a maximum length of 128 characters anddescription
a maximum length of 512 characters- There's a maximum count for each object type for Azure Policy. For definitions, an entry of Scope means the management group or subscription. For assignments and exemptions, an entry of Scope means the management group, subscription, resource group, or individual resource:
Where | What | Maximum count |
---|---|---|
Scope | Policy definitions | 500 |
Scope | Initiative definitions | 200 |
Tenant | Initiative definitions | 2,500 |
Scope | Policy or initiative assignments | 200 |
Scope | Exemptions | 1,000 |
Policy definition | Parameters | 20 |
Initiative definition | Policies | 1,000 |
Initiative definition | Parameters | 300 |
Policy or initiative assignments | Exclusions (notScopes) | 400 |
Policy rule | Nested conditionals | 512 |
Remediation task | Resources | 50,000 |
Policy definition, initiative, or assignment request body | Bytes | 1,048,576 |