Search code examples
azureterraform

Terraform deploy policy in Azure subscription: declare using "data" block instead of a "resource" block


I am trying to use terraform to manage policy assigned to a subscription. I am getting an error but I don't understand what the problem is. I appreciate any help or hint. Thank you.

policy.tf

provider "azurerm" {
  features {}
  subscription_id = "00000000-a0b0-0000-0a00-0f000000000"
}

resource "azurerm_policy_definition" "vm_sku_policy" {
  name         = "OnlyAllowHostingCROSImages"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "Limit allowed VM SKUs"
  description  = "This policy restricts the VM SKUs that can be deployed in the subscription."

  policy_rule = <<POLICY_RULE
  {
    "if": {
      "allOf": [
        {
          "field": "type",
          "in": [
            "Microsoft.Compute/virtualMachines",
            "Microsoft.Compute/virtualMachineScaleSets"
          ]
        },
        {
          "not": {
            "anyOf": [
              {
                "field": "Microsoft.Compute/imageSku",
                "like": "*-Datacenter-gs"
              },
              {
                "field": "Microsoft.Compute/imageSku",
                "like": "2022-Datacenter*"
              },
              {
                "allOf": [
                  {
                    "field": "Microsoft.Compute/imagePublisher",
                    "equals": "Canonical"
                  },
                  {
                    "field": "Microsoft.Compute/imageOffer",
                    "in": [
                      "0001-com-ubuntu-server-focal",
                      "0001-com-ubuntu-server-jammy",
                      "UbuntuServer"
                    ]
                  },
                  {
                    "field": "Microsoft.Compute/imageSku",
                    "in": [
                      "20_04-lts-gen2",
                      "20_04-lts-cvm",
                      "22_04-lts-cvm",
                      "20_04-lts",
                      "22_04-lts"
                    ]
                  }
                ]
              }
            ]
          }
        }
      ]
    },
    "then": {
      "effect": "deny"
    }
  }
POLICY_RULE
}


resource "azurerm_resource_group" "vm_sku_policy" {
  name     = "test-resources"
  location = "West Europe"
}

resource "azurerm_policy_assignment" "vm_sku_policy" {
  name                 = "limit-vm-sku-assignment"
  policy_definition_id = azurerm_policy_definition.vm_sku_policy.id
  scope                = "/subscriptions/00000000-a0b0-0000-0a00-0f000000000"
  display_name         = azurerm_policy_definition.vm_sku_policy.display_name
  description          = azurerm_policy_definition.vm_sku_policy.description
}

error:

PS C:\WindowsFabric\policy> terraform plan
╷
│ Error: Invalid resource type
│ 
│   on amir.tf line 105, in resource "azurerm_policy_assignment" "vm_sku_policy":
│  105: resource "azurerm_policy_assignment" "vm_sku_policy" {
│ 
│ The provider hashicorp/azurerm does not support resource type "azurerm_policy_assignment".
│
│ Did you intend to use the data source "azurerm_policy_assignment"? If so, declare this using a "data" block instead of a "resource" block.

Solution

  • The azurerm_policy_assignment is deprecated. You should use the azurerm_subscription_policy_assignment to assign the policy at subscription level. For more information, refer to the GitHub page.

    Here are are the supported blocks to assign the policy assignments on different scope, follow the Terraform Doc for more details

    enter image description here

    When I tried your code, I encountered the same error as follows

    enter image description here

    To create a policy definition and assign it at the subscription, you can use the updated code below.

    provider "azurerm" {
      features {}
      subscription_id = "158b8345-c359-4d98-95c5-f21815dd048f"
    }
    
    resource "azurerm_policy_definition" "vm_sku_policy" {
      name         = "OnlyAllowHostingCROSImages"
      policy_type  = "Custom"
      mode         = "All"
      display_name = "Limit allowed VM SKUs"
      description  = "This policy restricts the VM SKUs that can be deployed in the subscription."
    
      policy_rule = <<POLICY_RULE
      {
        "if": {
          "allOf": [
            {
              "field": "type",
              "in": [
                "Microsoft.Compute/virtualMachines",
                "Microsoft.Compute/virtualMachineScaleSets"
              ]
            },
            {
              "not": {
                "anyOf": [
                  {
                    "field": "Microsoft.Compute/imageSku",
                    "like": "*-Datacenter-gs"
                  },
                  {
                    "field": "Microsoft.Compute/imageSku",
                    "like": "2022-Datacenter*"
                  },
                  {
                    "allOf": [
                      {
                        "field": "Microsoft.Compute/imagePublisher",
                        "equals": "Canonical"
                      },
                      {
                        "field": "Microsoft.Compute/imageOffer",
                        "in": [
                          "0001-com-ubuntu-server-focal",
                          "0001-com-ubuntu-server-jammy",
                          "UbuntuServer"
                        ]
                      },
                      {
                        "field": "Microsoft.Compute/imageSku",
                        "in": [
                          "20_04-lts-gen2",
                          "20_04-lts-cvm",
                          "22_04-lts-cvm",
                          "20_04-lts",
                          "22_04-lts"
                        ]
                      }
                    ]
                  }
                ]
              }
            }
          ]
        },
        "then": {
          "effect": "deny"
        }
      }
    POLICY_RULE
    }
    
    data "azurerm_subscription" "current" {}
    
    resource "azurerm_resource_group" "vm_sku_policy" {
      name     = "test-resources"
      location = "West Europe"
    }
    
    resource "azurerm_subscription_policy_assignment" "example" {
      name                 = "exlimit-vm-sku-assignmentample"
      policy_definition_id = azurerm_policy_definition.vm_sku_policy.id
      subscription_id      = data.azurerm_subscription.current.id
    }
    
    

    Terraform apply

    After executing the terraform script, the policy definition has been created and assigned at subscription level.

    enter image description here