Search code examples
azureterraform-provider-azureazure-policy

Terraform: Create an Azure Policy Initiative with multiple custom Azure Policies with Parameters


I want to create an Azure Policy Initiative with multiple custom Azure Policies

I have the following custom policy

# Azure Provider source and version being used
terraform {
  required_providers {
    azurerm = {
        source = "hashicorp/azurerm"
        version = "~> 3.30.0"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {}
}

// Policy Category
variable "policy_definition_category" {
  type        = string
  description = "The category to use for all PolicySet defintions"
  default     = "Custom"
}   

// Policy Definition for Role Audit
resource "azurerm_policy_definition" "auditRoleAssignmentType" {
  name         = "auditRoleAssignmentType"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "Audit user role assignments"
  description  = "This policy checks for any Role Assignments of Type [User] - useful to catch individual IAM assignments to resources/RGs which are out of compliance with the RBAC standards e.g. using Groups for RBAC."

  metadata = <<METADATA
    {
    "category": "${var.policy_definition_category}",
    "version" : "1.0.0"
    }
METADATA

  policy_rule = <<POLICY_RULE
    {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Authorization/roleAssignments"
        },
        {
          "field": "Microsoft.Authorization/roleAssignments/principalType",
          "equals": "[parameters('principalType')]"
        }
      ]
    },
    "then": {
      "effect": "audit"
    }
  }
POLICY_RULE

  parameters = <<PARAMETERS
    {
    "principalType": {
      "type": "String",
      "metadata": {
        "displayName": "principalType",
        "description": "Which principalType to audit against e.g. 'User'"
      },
      "allowedValues": [
        "User",
        "Group",
        "ServicePrincipal"
      ],
      "defaultValue": "User"
    }
  }
PARAMETERS

}

// Display the Policy ID
output "auditRoleAssignmentType" {
  value       = "${azurerm_policy_definition.auditRoleAssignmentType.id}"
  description = "The policy definition id for auditRoleAssignmentType"
}

I have the following Initiative definition

// List of Policy Definitions for the Custom Initiative
variable "list_of_policies_definitions" {
  type        = list
  description = "List of policy definitions"
  default = [
    "auditRoleAssignmentType"
  ]
}

// Get the list of Policies
data "azurerm_policy_definition" "custom_policies_definitions" {
  count        = length(var.list_of_policies_definitions)
  display_name = var.list_of_policies_definitions[count.index]

  depends_on = [
    azurerm_policy_definition.auditRoleAssignmentType
  ]
}

// Define parameters for the Custom Initiative
variable "custom_initiative_parameters" {
  type        = list
  description = "List of policy definitions"
  default = [
    <<PARAMETERS
    {
      "principalType": {
        "value": "User"
      }
    }
    PARAMETERS,
    <<PARAMETERS
    {
      "paramfornextpolicy": {
        "value": "valuefornextpolicy"
      }
    }
    PARAMETERS    
  ]
}

// Initiative Category
variable "policyset_definition_category" {
  type        = string
  description = "The category to use for all PolicySet defintions"
  default     = "Custom"
}

// Initiative Definition 
resource "azurerm_policy_set_definition" "custom_initiative" {

  name         = "custom_initiative"
  policy_type  = "Custom"
  display_name = "Custom Initiative"
  description  = "Contains common policies"

  metadata = <<METADATA
    {
    "category": "${var.policyset_definition_category}"
    }
METADATA

  dynamic "policy_definition_reference" {
    for_each = data.azurerm_policy_definition.custom_policies_definitions
    content {
      policy_definition_id = policy_definition_reference.value["id"]
      reference_id         = policy_definition_reference.value["id"]
      parameters           = var.custom_initiative_parameters["id"]
    }
  }

  depends_on = [
    data.azurerm_policy_definition.custom_policies_definitions
  ]
}

I am getting the following error

│ Error: Unsupported argument │ │ on main.tf line 151, in resource "azurerm_policy_set_definition" "custom_initiative": │
151: parameters = var.custom_initiative_parameters["id"] │
│ An argument named "parameters" is not expected here.

I understand that "parameter_values" should be used, but I'm not sure how?


Solution

  • This I how you Pass parameter_values:

    You can pass parameter_values as shown here:

    PARAMETERS
      policy_definition_reference {
        policy_definition_id = azurerm_policy_definition.test.id
        parameter_values = jsonencode({ //"`jsonencode` -> Converts into json parameter file"
          allowedLocations = { value: "[parameters('allowedLocations')]"}
        })
      }
    }
    

    After adding values, I modified & tried to create a custom policy definition to see if the parameter values were being given.

    It worked for me as expected and added terraform code below:

    vi main.tf:

    terraform {
      required_providers {
        azurerm = {
          source = "hashicorp/azurerm"
          version = "3.35.0"
        }
      }
    }
    provider "azurerm" {
      features {}
    }
    resource "azurerm_policy_definition" "example" {
      name         = "xxxxx"
      policy_type  = "Custom"
      mode         = "All"
      display_name = "xxxx"
      policy_rule = <<POLICY_RULE
        {
        "if": {
          "not": {
            "field": "location",
            "in": "[parameters('allowedLocations')]"
          }
        },
        "then": {
          "effect": "audit"
        }
      }
    POLICY_RULE
      parameters = <<PARAMETERS
      {
        "allowedLocations": {
          "type": "Array",
          "metadata": {
            "description": "The list of allowed locations for resources.",
            "displayName": "Allowed locations",
            "strongType": "location"
          }
        }
      }
    PARAMETERS
    }
    resource "azurerm_policy_set_definition" "example" {
      name         = "xxxx-example"
      policy_type  = "Custom"
      display_name = "xxxxxx-example"
      parameters = <<PARAMETERS
        {
            "allowedLocations": {
                "type": "Array",
                "metadata": {
                    "description": "List of allowed locations.",
                    "displayName": "Allowed locations",
                    "strongType": "location"
                }
            }
        }
    PARAMETERS
      policy_definition_reference {
        policy_definition_id = azurerm_policy_definition.example.id
        parameter_values = jsonencode({
          allowedLocations = { value: "[parameters('allowedLocations')]"}
        })
      }
    }
    

    terraform plan:

    enter image description here

    terraform apply:

    enter image description here

    Policy definition added in the Portal with parameter values:

    enter image description here