Bicep module files for policy definition versus using the File Function #17
-
Hey @jesseloudon I have been using a similar approach as you and have referenced your code a lot - thanks for sharing it. One thing i am interested to get your view. I have been using Bicep module files to build the metric alerts and then referencing them in a definitions.bicep file. I notice you use the Function json(loadTextContent()) to pull in the JSON into the definitions.bicep file. What do see are the advantages to that approach over using bicep modules for the definitions? I know the definitions are pretty much JSON anyway :) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @mcdrm - great question! Having custom policy definitions stored in .JSON format instead of .BICEP format allows me to quickly copy + paste + create custom policies directly from the Azure Portal, or any public repo containing .JSON policies, without doing any modifications to the new .JSON file. Some modifications you can avoid by using this pattern would be:
There are disadvantages to using this pattern such as:
Custom policy example with Bicep (for comparison with JSON example below): targetScope = 'subscription'
// PARAMETERS
param policySource string
param policyCategory string
param mandatoryTag1Key string
param mandatoryTag1Value string
// OUTPUTS
output policyID string = policy.id
// RESOURCES
resource policy 'Microsoft.Authorization/policyDefinitions@2020-09-01' = {
//level2
name: 'addTagToRG'
properties: {
displayName: 'Add tag to resource group'
policyType: 'Custom'
mode: 'All'
description: 'Adds the mandatory tag key when any resource group missing this tag is created or updated. Existing resource groups can be remediated by triggering a remediation task. If the tag exists with a different value it will not be changed.'
metadata: {
category: policyCategory
source: policySource
version: '0.1.0'
}
parameters: {
tagName: {
type: 'String'
metadata: {
displayName: 'Mandatory Tag ${mandatoryTag1Key}'
description: 'Name of the tag, such as ${mandatoryTag1Key}'
}
defaultValue: 'BicepTagName'
}
tagValue: {
type: 'String'
metadata: {
displayName: 'Tag Value ${mandatoryTag1Value}'
description: 'Value of the tag, such as ${mandatoryTag1Value}'
}
defaultValue: 'tempvalue'
}
}
policyRule: {
if: {
allOf: [
{
field: 'type'
equals: 'Microsoft.Resources/subscriptions/resourceGroups'
}
{
field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]'
exists: 'false'
}
]
}
then: {
effect: 'modify'
details: {
roleDefinitionIds: [
'/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c'
]
operations: [
{
operation: 'add'
field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]'
value: '[parameters(\'tagValue\')]'
}
]
}
}
}
}
} Custom policy example with JSON (for comparison with Bicep example above): {
"properties": {
"displayName": "Add mandatory tag to resource group",
"policyType": "Custom",
"mode": "All",
"description": "Adds the mandatory tag key when any resource group missing this tag is created or updated. If the tag exists with a different value it will not be changed.",
"metadata": {
"category": "Custom",
"source": "github.com/globalbao/azure-policy-as-code",
"version": "1.0.0"
},
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag name",
"description": "Name of the tag, such as 'CostCenter'"
}
},
"tagValue": {
"type": "String",
"metadata": {
"displayName": "Tag value",
"description": "Value of the tag e.g. '12345'"
}
},
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": ["Audit", "Modify", "Disabled"],
"defaultValue": "Modify"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
}
]
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"operations": [
{
"operation": "add",
"field": "[concat('tags[', parameters('tagName'), ']')]",
"value": "[parameters('tagValue')]"
}
]
}
}
}
}
} In my view having the Bicep function json(loadTextContent()) available to use is an absolute bonus but not a silver bullet to every problem. Having these various options for Bicep users to consume Azure policies is a very good experience given the different use cases and circumstances. Cheers |
Beta Was this translation helpful? Give feedback.
Hi @mcdrm - great question!
Having custom policy definitions stored in .JSON format instead of .BICEP format allows me to quickly copy + paste + create custom policies directly from the Azure Portal, or any public repo containing .JSON policies, without doing any modifications to the new .JSON file.
Some modifications you can avoid by using this pattern would be:
There are disadvantages to using this pattern such as: