Quickstart: Create a policy assignment to identify non-compliant resources using Terraform
The first step in understanding compliance in Azure is to identify the status of your resources. This quickstart steps you through the process of creating a policy assignment to identify virtual machines that aren't using managed disks.
At the end of this process, you identify virtual machines that aren't using managed disks across subscription. They're non-compliant with the policy assignment.
When assigning a built-in policy or initiative definition, it's optional to reference a version. Policy assignments of built-in definitions default to the latest version and automatically inherit minor version changes unless otherwise specified.
Prerequisites
- If you don't have an Azure subscription, create a free account before you begin.
- Terraform version 0.12.0 or higher configured in your environment. For instructions, see Configure Terraform using Azure Cloud Shell.
- This quickstart requires that you run Azure CLI version 2.13.0 or later. To find the version, run
az --version
. If you need to install or upgrade, see Install Azure CLI.
Create the Terraform configuration, variable, and output file
In this quickstart, you create a policy assignment and assign the Audit VMs that do not use managed disks definition. This policy definition identifies resources that aren't compliant to the conditions set in the policy definition.
Configure the Terraform configuration, variable, and output files. The Terraform resources for Azure Policy use the Azure Provider.
Create a new folder named
policy-assignment
and change directories into it.Create
main.tf
with the following code:Note
To create a Policy Assignment at a Management Group use the azurerm_management_group_policy_assignment resource, for a Resource Group use the azurerm_resource_group_policy_assignment and for a Subscription use the azurerm_subscription_policy_assignment resource.
provider "azurerm" { features {} } terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = ">= 2.96.0" } } } resource "azurerm_subscription_policy_assignment" "auditvms" { name = "audit-vm-manageddisks" subscription_id = var.cust_scope policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" description = "Shows all virtual machines not using managed disks" display_name = "Audit VMs without managed disks assignment" }
Create
variables.tf
with the following code:variable "cust_scope" { default = "{scope}" }
A scope determines what resources or grouping of resources the policy assignment gets enforced on. It could range from a management group to an individual resource. Be sure to replace
{scope}
with one of the following patterns based on the declared resource:- Subscription:
/subscriptions/{subscriptionId}
- Resource group:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}
- Resource:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]
- Subscription:
Create
output.tf
with the following code:output "assignment_id" { value = azurerm_subscription_policy_assignment.auditvms.id }
Initialize Terraform and create plan
Initialize Terraform to download the necessary providers and then create a plan.
Run the terraform init command. This command downloads the Azure modules required to create the Azure resources in the Terraform configuration.
terraform init
Authenticate with Azure CLI for Terraform. For more information, see Azure Provider: Authenticating using the Azure CLI.
az login
Create the execution plan with the terraform plan command and out parameter.
terraform plan -out assignment.tfplan
Note
For information about persisting execution plans and security, see Terraform Plan: Security Warning.
Apply the Terraform execution plan
Apply the execution plan.
Run the terraform apply command and specify the
assignment.tfplan
already created.
terraform apply assignment.tfplan
With the Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
message, the policy
assignment is now created. Since we defined the outputs.tf
file, the assignment_id is also
returned.
Identify non-compliant resources
To view the resources that aren't compliant under this new assignment, use the assignment_id
returned by terraform apply
. With it, run the following command to get the resource IDs of the
non-compliant resources that are output into a JSON file:
armclient post "/subscriptions/<subscriptionID>/providers/Microsoft.PolicyInsights/policyStates/latest/queryResults?api-version=2019-10-01&$filter=IsCompliant eq false and PolicyAssignmentId eq '<policyAssignmentID>'&$apply=groupby((ResourceId))" > <json file to direct the output with the resource IDs into>
Your results resemble the following example:
{
"@odata.context": "https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.PolicyInsights/policyStates/$metadata#latest",
"@odata.count": 3,
"value": [
{
"@odata.id": null,
"@odata.context": "https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.PolicyInsights/policyStates/$metadata#latest/$entity",
"ResourceId": "/subscriptions/<subscriptionId>/resourcegroups/<rgname>/providers/microsoft.compute/virtualmachines/<virtualmachineId>"
},
{
"@odata.id": null,
"@odata.context": "https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.PolicyInsights/policyStates/$metadata#latest/$entity",
"ResourceId": "/subscriptions/<subscriptionId>/resourcegroups/<rgname>/providers/microsoft.compute/virtualmachines/<virtualmachine2Id>"
},
{
"@odata.id": null,
"@odata.context": "https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.PolicyInsights/policyStates/$metadata#latest/$entity",
"ResourceId": "/subscriptions/<subscriptionName>/resourcegroups/<rgname>/providers/microsoft.compute/virtualmachines/<virtualmachine3ID>"
}
]
}
The results are comparable to what you'd typically see listed under Non-compliant resources in the Azure portal view.
Clean up resources
To remove the assignment created, use Azure CLI or reverse the Terraform execution plan with
terraform destroy
.
Azure CLI
az policy assignment delete --name 'audit-vm-manageddisks' --scope '/subscriptions/<subscriptionID>/<resourceGroupName>'
Terraform
terraform destroy
Next steps
In this quickstart, you assigned a policy definition to identify non-compliant resources in your Azure environment.
To learn more about assigning policies to validate that new resources are compliant, continue to the tutorial for: