Table of Contents
- Step 1 – Create Resource Group and Base Terraform Setup
- Step 2 – Create Mandatory Tag Policy
- Step 3 – Create Allowed VM Size Policy
- Step 4 – Create Allowed Location Policy
- Final Outcome of This Mini Project
In this mini project, we implement Azure governance using Terraform. The goal is to enforce organizational standards at the subscription level using Azure Policy—so that resources follow rules for:
- Mandatory tags
- Allowed VM sizes
- Allowed deployment locations
Everything is automated using Terraform infrastructure as code.
Step 1 – Create Resource Group and Base Terraform Setup
We start by creating:
- A resource group
- Variables for locations, VM sizes, and allowed tags
- Output to display current subscription ID
Resource Group – rg.tf
resource "azurerm_resource_group" "rg" {
name = "rgminipro7878"
location = "Central US"
}
Read Current Subscription – main.tf
data "azurerm_subscription" "subscriptioncurrent" {}
Output Subscription ID – output.tf
output "subscription_id" {
value = data.azurerm_subscription.subscriptioncurrent.id
}
Variables – variables.tf
variable "location" {
type = list(string)
default = ["eastus", "westus"]
}
variable "vm_sizes" {
type = list(string)
default = ["Standard_B2s", "Standard_B2ms"]
}
variable "allowed_tags" {
type = list(string)
default = ["department", "project"]
}
After running:
terraform apply
✔ Resource group was created
✔ Subscription ID output was verified
Step 2 – Create Mandatory Tag Policy
Next, we enforce that every resource must contain two tags:
- department
- project
If either tag is missing → resource creation is denied.
Policy Definition – policy1.tf
resource "azurerm_policy_definition" "tagpolicy" {
name = "allowed-tag"
policy_type = "Custom"
mode = "All"
display_name = "Allowed tags policy"
policy_rule = jsonencode({
if = {
anyOf = [
{
field = "tags[${var.allowed_tags[0]}]"
exists = false
},
{
field = "tags[${var.allowed_tags[1]}]"
exists = false
}
]
}
then = {
effect = "deny"
}
})
}
Assign Policy to Subscription
resource "azurerm_subscription_policy_assignment" "tag_assign" {
name = "tag-assignment"
policy_definition_id = azurerm_policy_definition.tagpolicy.id
subscription_id = data.azurerm_subscription.subscriptioncurrent.id
}
⚠ Important
To create and assign policies, your account must have:
Resource Policy Contributor role.
Testing the Policy – testrg.tf
resource "azurerm_resource_group" "bad" {
name = "bad-rg"
location = "Central US"
tags = {
department = "IT"
project = "Demo"
}
}
✔ Without tags → RG creation blocked
✔ With tags → RG creation allowed
Step 3 – Create Allowed VM Size Policy
Now we restrict which VM sizes can be used.
Allowed sizes:
- Standard_B2s
- Standard_B2ms
Policy Definition – policy2.tf
resource "azurerm_policy_definition" "vm_size" {
name = "vm-size"
policy_type = "Custom"
mode = "All"
display_name = "Allowed vm policy"
policy_rule = jsonencode({
if = {
field = "Microsoft.Compute/virtualMachines/sku.name"
notIn = [
var.vm_sizes[0],
var.vm_sizes[1]
]
}
then = {
effect = "deny"
}
})
}
Assign VM Size Policy
resource "azurerm_subscription_policy_assignment" "vm_assign" {
name = "size-assignment"
policy_definition_id = azurerm_policy_definition.vm_size.id
subscription_id = data.azurerm_subscription.subscriptioncurrent.id
}
✔ Any VM outside allowed list → blocked
✔ Governance enforced at subscription level
Step 4 – Create Allowed Location Policy
Finally, we restrict deployments only to:
- eastus
- westus
Policy Definition – policy3.tf
resource "azurerm_policy_definition" "location" {
name = "location"
policy_type = "Custom"
mode = "All"
display_name = "Allowed location policy"
policy_rule = jsonencode({
if = {
field = "location"
notIn = [
var.location[0],
var.location[1]
]
}
then = {
effect = "deny"
}
})
}
Assign Location Policy
resource "azurerm_subscription_policy_assignment" "loc_assign" {
name = "location-assignment"
policy_definition_id = azurerm_policy_definition.location.id
subscription_id = data.azurerm_subscription.subscriptioncurrent.id
}
✔ Resources in other regions → denied
✔ Standardized deployment geography
Final Outcome of This Mini Project
Using Terraform + Azure Policy we achieved:
✔ Mandatory tagging for all resources
✔ Standard VM sizes enforced
✔ Controlled allowed regions
✔ Governance at subscription level
✔ Fully automated with IaC
This approach is ideal for:
- Enterprise governance
- Cost control
- Security compliance
- Standardization across teams

Leave a Reply