My current task is to take all of our azure policy definitions and initiatives and define them as code. then upload them through azure pipelines. This has gone fine when working with policy definitions. However I run into trouble, when i try to upload (create) the azure policy initiatives with azure powershell.
The way i have downloaded all the azure initiatives (we have only 10), is that I went into the azure portal and copy pasted the json file that created the initiatives. Here is an example of an initiative im using:
{"properties": {
"displayName": "Backup standards",
"description": "Policy initiative for backup standards.",
"policyType": "Custom",
"metadata": {
"category": "Backup"
},
"parameters": {},
"policyDefinitions": [
{
"policyDefinitionReferenceId": "Backup - SQL Databases (LTR)_1",
"policyDefinitionId": "/providers/Microsoft.Management/managementGroups/mg_ascendis/providers/Microsoft.Authorization/policyDefinitions/42e7bc7d-5269-4df1-b7bc-c412b7471a78",
"parameters": {},
"groupNames": []
},
{
"policyDefinitionReferenceId": "Backup - SQL Managed Instance Databases (LTR)_1",
"policyDefinitionId": "/providers/Microsoft.Management/managementGroups/mg_ascendis/providers/Microsoft.Authorization/policyDefinitions/2fdbaa21-166a-4ce2-8436-e2b6d02db579",
"parameters": {},
"groupNames": []
},
{
"policyDefinitionReferenceId": "Backup - SQL Databases (STR)_1",
"policyDefinitionId": "/providers/Microsoft.Management/managementGroups/mg_ascendis/providers/Microsoft.Authorization/policyDefinitions/576dd0b4-0b59-4aed-b51d-529ce4ad5965",
"parameters": {},
"groupNames": []
},
{
"policyDefinitionReferenceId": "Backup - SQL Managed Instance Databases (STR)_1",
"policyDefinitionId": "/providers/Microsoft.Management/managementGroups/mg_ascendis/providers/Microsoft.Authorization/policyDefinitions/88128b89-a983-48d9-94fb-b3d94060e0e3",
"parameters": {},
"groupNames": []
}
],
"policyDefinitionGroups": []},
"id": "/providers/Microsoft.Management/managementGroups/mg_ascendis/providers/Microsoft.Authorization/policySetDefinitions/70746fa2e0af49b2bd08cc39",
"type": "Microsoft.Authorization/policySetDefinitions",
"name": "70746fa2e0af49b2bd08cc39"
}
When i upload this with the following command
New-AzPolicySetDefinition -Name $name -Subscription $Subscription -Policy $Path_To_json_file
i get the error: New-AzPolicySetDefinition: The provided value for parameter 'PolicyDefinition' is not a valid JSON array
The current solution i use to (try) upload all my 10 initiatives is this azure powershell script (I got 10 folders with the name of the initiative. Within each of those folder is a file called initiative.json with the initiative as a json object):
$Subscription = "xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$dirs = Get-ChildItem -Directory
foreach ($dir in $dirs){
$full_dir = $dir.FullName + "/initiative.json"
$folder_name = $dir.Name
$json = Get-Content $full_dir | Out-String | ConvertFrom-Json
# save part of the json file
$save_location = $dir.FullName + "/init_def_json"
$json.properties.policydefinitions| ConvertTo-Json -depth 100 | Out-File
$save_location
New-AzPolicySetDefinition -Name $folder_name -DisplayName
$json.properties.displayname -Description $json.properties.description -Subscription
$Subscription -PolicyDefinition $save_location
}
I find this solution quite bad, also because the initiative fails to upload when there are parameters in the initiative, and i have not been able to fix this. Does anyone know a good way of uploading azure policy initiatives through azure powershell? one that preferably just used the base json file i posted in the beginning.
The provided value for parameter 'Policy Definition' is not a valid JSON array.
There is a particular JSON structure to follow while creating an initiative definition.
Structure contains:
- display name
- description
- metadata
- parameters
- policy definitions
- policy groups
As detailed in this MsDocs. You can find the clear and exact structure in the above document to create a custom policy initiative.
The error means that the "PolicyDefinition"
field expects a JSON
array instead it receives a JSON
object.
The "PolicyDefinition"
element specifies one or more policy definitions related to the policy initiative. It means that you need to send that array to the "PolicyDefinition"
field.
I've taken a sample policy definition id's and it worked for me as follows:
{
"properties": {
"displayName": "<name>",
"policyType": "custom",
"description": "authorization",
"metadata": {
"category": "Monitoring"
},
"parameters": {},
"policyDefinitions": [
{
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/2a0e14a6-b0a6-4fab-991a-187a4f81c498",
"parameters": {
"tagName": {
"value": ""
}
}
},
{
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/464dbb85-3d5f-4a1d-bb09-95a9b5dd19cf",
"parameters": {}
}
]
}
}
Note: The code provided by you looks good. If still the issue persists, double check the structure of the JSON and modify it accordingly as per your requirement. Check the policydefintiongroups
as well as closing braces correctly.
Sample structure of policydefintiongroups
:
"policyDefinitionGroups": [
{
"name": "",
"Id": ""
}
]
Alternatively, modify the command as below to read the JSON file and pass it to the policy defintion parameter.
$json = Get-Content < path of the Json policy > | ConvertFrom-Json
New-AzPolicySetDefinition -Name <name> -DisplayName $json.properties.displayName -Description <description> -PolicyDefinition $json.properties.policyDefinitions
Output:
And you can also refer MSDoc for more relevant information.