Search code examples
azureterraformazure-policy

Terraform - audit tags with Azure policy


I am trying to create an Azure policy with Terraform. The policy needs to audit on resources that do not comply to the tag 'Environment' with 'Production' as a value. I am getting an error and cannot figure out what goes wrong in the code. I am using the following policy.tf.

variable "requiredTag" {
  default = "environment"
}

variable "requiredValue" {
  default = "production"
}

data "azurerm_subscription" "current" {}

resource "azurerm_policy_definition" "tagging-policy" {
  name         = "check-tags"
  display_name = "Check for required tags"
  description  = "This policy checks if a specific tag is set on resources"

  policy_type = "Custom"
  mode        = "All"

  metadata = <<METADATA
    {
    "category": "Tags"
    }
  METADATA

  policy_rule = <<POLICY_RULE
  {
    "if": {
      "not": {
        "field": "[concat('tags[', parameters('tagName'), ']')]",
        "equals": "[parameters('tagValue')]"
      }
    },
    "then": {
        "effect": "audit"
    }
}
POLICY_RULE
  parameters  = <<PARAMETERS
  {
    "tagName": {
        "type": "String",
        "metadata": {
            "displayName": "Tag Name",
            "description": "Name of the tag, such as 'environment'"
        }
    },
    "tagValue": {
        "type": "String",
        "metadata": {
            "displayName": "Tag Value",
            "description": "Value of the tag, such as 'production'"
        },
        "defaultValue": [ "production" ]
    }
    
}
PARAMETERS
}

resource "azurerm_subscription_policy_assignment" "assign-tagging-policy" {
  name                 = azurerm_policy_definition.tagging-policy.name
  policy_definition_id = azurerm_policy_definition.tagging-policy.id
  subscription_id      = data.azurerm_subscription.current.id

    parameters  =<<PARAMETERS
  {
    "tagValue": {
        "value": "${var.requiredValue}"
    },
    "tagName": {
        "value": "${var.requiredTag}"
    }
}
PARAMETERS
}

I am getting the following error:

Error: creating/updating Policy Definition "check-tags": policy.DefinitionsClient#CreateOrUpdate: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="InvalidPolicyParameterType" Message="The policy parameter 'tagValue' default value does not match the expected parameter type defined in the policy definition 'check-tags'. Details 'The expected policy parameter type: 'String'. The actual policy parameter type 'Array'.'."
│
│   with module.tags.azurerm_policy_definition.tagging-policy,
│   on tags\tagging-policy.tf line 3, in resource "azurerm_policy_definition" "tagging-policy":
│    3: resource "azurerm_policy_definition" "tagging-policy" {

Thanks in advance for any help!

I've compared the json code to the json code of a builtin policy but as far as I can see there is no error in my code.


Solution

  • I got the same error when I tried it before in my environment. I found the cause of the issue. You are defining "defaultValue": ["production"] in the "azurerm policy definition" block. It means you're passing it as an array, but the tag value type it accepts is String. I modified it to "defaultValue": "production".

    "tagValue": {
            "type": "String",
            "metadata": {
                "displayName": "Tag Value",
                "description": "Value of the tag, such as 'production'"
            },
            "defaultValue": "production"
        }
    

    And I've included the complete modified script by taking your original code as below:

    main.tf:

    provider "azurerm" {
    features{}
    }
    variable "requiredTag" {
      default = "environment"
    }
    
    variable "requiredValue" {
      default = "production"
    }
    
    data "azurerm_subscription" "current" {}
    
    resource "azurerm_policy_definition" "tagging-policy" {
      name         = "check-tags"
      display_name = "Check for required tags"
      description  = "This policy checks if a specific tag is set on resources"
    
      policy_type = "Custom"
      mode        = "All"
    
      metadata = <<METADATA
        {
        "category": "Tags"
        }
      METADATA
    
      policy_rule = <<POLICY_RULE
      {
        "if": {
          "not": {
            "field": "[concat('tags[', parameters('tagName'), ']')]",
            "equals": "[parameters('tagValue')]"
          }
        },
        "then": {
            "effect": "audit"
        }
    }
    POLICY_RULE
      parameters  = <<PARAMETERS
      {
        "tagName": {
            "type": "string",
            "metadata": {
                "displayName": "Tag Name",
                "description": "Name of the tag, such as 'environment'"
            }
        },
        "tagValue": {
            "type": "String",
            "metadata": {
                "displayName": "Tag Value",
                "description": "Value of the tag, such as 'production'"
            },
            "defaultValue": "production"
        }
        
    }
    PARAMETERS
    }
    
    resource "azurerm_subscription_policy_assignment" "assign-tagging-policy" {
      name                 = azurerm_policy_definition.tagging-policy.name
      policy_definition_id = azurerm_policy_definition.tagging-policy.id
      subscription_id      = data.azurerm_subscription.current.id
    
        parameters  =<<PARAMETERS
      {
        "tagValue": {
            "value": "${var.requiredValue}"
        },
        "tagName": {
            "value": "${var.requiredTag}"
        }
    }
    PARAMETERS
    }
    

    Executed terraform init & validated the configuration using terraform validate:

    enter image description here

    Executed terraform plan

    enter image description here

    Executed terraform apply -auto-approve

    enter image description here

    Check-tags policy is successfully deployed and applied in Portal:

    enter image description here