'Powershell Az to create Azure Policy in an Initiative That Accepts An Array Parameters

Got a powershell script that creates Azure Policy and assign it to an Initiative with a single parameter. I’m unable to create an Initiative parameters that takes an array of values, and link it to the Initiative.

We do not want resource groups created unless it has the three mandatory tags: Security Owner, tagTwo, and tagThree. So, an Azure Policy Initiative is created with a Policy Rule that checks if the tag exists. I like this design pattern because if we have additional tags as requirement on the Resource Group then we'll add to the Initiative Parameter rather than creating a new Policy.

Here’s what I have so far. The policy rule in a json file (append_rg_tag.json)

{
"if": {
    "allOf": [
        {
            "field": "type",
            "equals": "Microsoft.Resources/subscriptions/resourceGroups"
        },
        {
            "field": "[concat('tags[', parameters('tagName'), ']')]",
            "exists": "false"
        }
    ]
},
"then": {
    "effect": "deny"
}
}

The parameter for the Policy in a json file (append_tag_parameters.json)

{
"tagName": {
    "type": "String",
    "metadata": {
        "displayName": "Tag Name",
        "description": "Name of the tag, such as 'Security Owner'"
    }
}
}

Putting it together, here’s the powershell script that creates the Azure Policy, and creates and assign the policy to the Initiative

# Create a new policy definition
$defParams = @{
Name = "TagResourceGroup"
DisplayName = "Deny Resource Group without a Tag"
Description = "Deny Resource Group without a Tag"
Metadata = '{"category":"Tags"}'
Parameter = "append_tag_parameters.json"
Policy = "append_rg_tag.json"
}
$definition = New-AzPolicyDefinition @defParams

# Create an initiative for tags
    $PolicyDefinition = @"
[
    {
        "policyDefinitionId": "$($definition.ResourceId)",
        "parameters": {
            "tagName": {
                "value": "Security Owner"
            }
        }
    }
]
"@

$initiativeParams = @{
    Name = "TagsSetResourceGroups"
    DisplayName = "Need Tag For Resource Group"
    Description = "Need Tag For Resource Group"
    Metadata = '{"category":"Tags"}'
    # Parameter = '{ Think something goes here, but am stuck}'
    PolicyDefinition = $PolicyDefinition
}

$initiative = New-AzPolicySetDefinition @initiativeParams

# Assign the initiave to the subscription

$assignParams = @{
    Name = "NeedTagForResourceGroup"
    DisplayName = "Tags for Resource Groups"
    Scope = "/subscriptions/$((Get-AzContext).Subscription.Id)"
    # PolicyParameterObject = @{Think something goes here, but am stuck}
    PolicySetDefinition = $initiative
}

New-AzPolicyAssignment @assignParams

Here's what it looks like in Azure

Policy View

Initiative Definition

Edit Initiative Definition

The Initiative Parameters would look like this if I were to create it manually in the Azure Portal

Edit Initiative Parameter

Thank you for reading and for your help!!



Solution 1:[1]

As a workaround and to simplify the policy; the following will deny a resource group from being created if it does not have the three tag names

deny_rg_tag.json

{
    "if": {
        "allOf": [
                {
                    "field": "type",
                    "equals": "Microsoft.Resources/subscriptions/resourceGroups"
                },
                {
                    "anyOf": [
                        {
                            "field": "[concat('tags[', parameters('tagName01'), ']')]",
                            "exists": "false"                      
                        },
                        {
                            "field": "[concat('tags[', parameters('tagName02'), ']')]",
                            "exists": "false"                      
                        },
                        {
                            "field": "[concat('tags[', parameters('tagName03'), ']')]",
                            "exists": "false"                      
                        }
                    ]
                }
        ]
    },
    "then": {
      "effect": "deny"
    }
}

deny_tag_parameters.json

{
    "tagName01": {
      "type": "String",
      "metadata": {
        "displayName": "Tag Name 01",
        "description": "Resource Group should have a tag "
      }
  },
    "tagName02": {
      "type": "String",
      "metadata": {
        "displayName": "Tag Name 02",
        "description": "Resource Group should have a tag "
      }
  },
    "tagName03": {
      "type": "String",
      "metadata": {
        "displayName": "Tag Name 03",
        "description": "Resource Group should have a tag "
      }
  }
}

Putting it together

$defParams = @{
    Name = "TagResourceGroup"
    DisplayName = "Deny Resource Group without a Tag"
    Description = "Deny Resource Group without a Tag"
    Metadata = '{"category":"Tags"}'
    Parameter = "deny_tag_parameters.json"
    Policy = "deny_rg_tag.json"
}

$definition = New-AzPolicyDefinition @defParams

# Create the Policy Assignment
New-AzPolicyAssignment -Name 'Resource Group Require Tags' `
                       -DisplayName 'Resource Group Require Tags' `
                       -Scope "/subscriptions/$((Get-AzContext).Subscription.Id)" `
                       -PolicyDefinition $definition

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 scv