Defining Policy as Code with ARM Templates

My colleagues and friends Tao Yang , and Stanislav Zhelyazkov have both recently posts interesting topics on how to implement your Azure Policy as Code which I strongly recommend you take a few moments to review

Improving Readability

Both of these topics address the core of the challenges we face when approaching policy as an Infrastructure as Code problem. However, one of the things that is lost in the translation is the readability of the templates which they are deploying.

Author: Damian
Published:
Updated:

My colleagues and friends Tao Yang , and Stanislav Zhelyazkov have both recently posts interesting topics on how to implement your Azure Policy as Code which I strongly recommend you take a few moments to review

Improving Readability

Both of these topics address the core of the challenges we face when approaching policy as an Infrastructure as Code problem. However, one of the things that is lost in the translation is the readability of the templates which they are deploying.

Not to reinvent the wheel, I am going to use the same template which Stan presented in his post, and make a small tweak to the process which he has employed to deal with the ' single quote problem!

ARM follows most of the standard JSON escape sequences, therefore the following examples are quite useful

Escaping a Single quote

Azure ARM behaves nicely with a simply doubling the single quote characters; just as we apply in Visual Basic.

[concat('This is a ''quoted'' word.')] which then provides the output of This is a 'quoted' word.

Escaping a Double quote

For the Double quotes, we use the normal escape character /.

[concat('''single'' and \"double\" quotes.')] will render the output as follows 'single' and "double" quotes.

The Solution

With this simple trick, we can replace the variables definition which the guys used with the following snippet:

json

  "variables": {
     "filterVNetId": "[ concat( '[concat(parameters(''virtualNetworkId''),''*'')]' ) ]"
   }

I am sure that this is a lot easier to read, and therefor debug; So the full template would look as follows

json

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "vNetId": {
      "type": "string",
      "defaultValue": "ScreenConnect"
    }
  },
  "variables": {
    "filterVNetId": "[ concat( '[concat(parameters(''virtualNetworkId''),''*'')]' ) ]"
  },
  "resources": [
    {
      "name": "vm-creation-in-approved-vnet-definition",
      "type": "Microsoft.Authorization/policyDefinitions",
      "apiVersion": "2018-03-01",
      "properties": {
        "displayName": "Use approved vNet for VM network interfaces",
        "policyType": "Custom",
        "mode": "All",
        "description": "Use approved vNet for VM network interfaces",
        "metadata": {
          "category": "IaaS"
        },
        "parameters": {
          "virtualNetworkId": {
            "type": "string",
            "metadata": {
              "description": "Resource Id for the vNet",
              "displayName": "vNet Id"
            }
          }
        },
        "policyRule": {
          "if": {
            "allOf": [
              {
                "field": "type",
                "equals": "Microsoft.Network/networkInterfaces"
              },
              {
                "not": {
                  "field": "Microsoft.Network/networkInterfaces/ipconfigurations[*].subnet.id",
                  "like": "[variables('filterVNetId')]"
                }
              }
            ]
          },
          "then": {
            "effect": "deny"
          }
        }
      }
    },
    {
      "name": "vm-creation-in-approved-vnet-assignment",
      "type": "Microsoft.Authorization/policyAssignments",
      "apiVersion": "2018-03-01",
      "dependsOn": [
        "[resourceId('Microsoft.Authorization/policyDefinitions/', 'vm-creation-in-approved-vnet-definition')]"
      ],
      "properties": {
        "displayName": "Use approved vNet for VM network interfaces",
        "description": "Use approved vNet for VM network interfaces",
        "metadata": {
          "assignedBy": "Admin"
        },
        "scope": "[subscription().id]",
        "policyDefinitionId": "[resourceId('Microsoft.Authorization/policyDefinitions', 'vm-creation-in-approved-vnet-definition')]",
        "parameters": {
          "virtualNetworkId": {
            "value": "[parameters('vNetId')]"
          }
        }
      }
    }
  ],
  "outputs": {}
}

Summary

Using native escape sequences in ARM assist in the overall readability of the final code.

Thank you Tao and Stan for the inspiration

All links in a practical list

More articles

Thoughts, topics or just solutions I would like to make available to you, colleagues and fellow enthusiasts.

Using AI to Empower Cloud Architecture and Deployments

The integration of artificial intelligence (AI) into cloud infrastructure is revolutionizing how we manage and deploy cloud resources. AI, now a pivotal component, optimizes the entire lifecycle of cloud architecture, enhancing tasks like deployment, maintenance, and scaling. This article explores the role of AI in empowering cloud architecture and deployments, especially when combined with Infrastructure as Code (IaC) tools like Bicep and Terraform.

Bicep - Tags as Parameters

Deploying infrastructure ARM Templates to Azure, but using Tags and their respective value as the parameter configuration settings

In a post earlier, we look at using arm to lookup the value of tags’ at both the Subscription and Resource Level.

With Bicep this is much easier to understand. This is the same lab configuration as in the original post, but this time to code should be a lot more readable.

Azure IaC - Tags as Parameters

Deploying infrastructure ARM Templates to Azure, but using Tags and thier respective value as the parameter configuration settings

In the post, I am going to introduce a concept which will allow you to greatly up your Infrastructure as Code game, by using Azure as a State Machine!

One of the typical challenges when deploying ARM templates, is the sheer number of parameters which we find as a requirement to complete a deployment; which as you will appreciate gets considerably harder as we target many environments.

Azure IaC - Function Keys

Retrieve the Function Host Keys while deploying an ARM template

Todays conundrum: As I deploy a new Function Application, I need a simple methodology to retrieve the Host Keys for the function application so that I validate the deployment has been successful; and potentially pass on the key to related services, for example API Management.

As before, I am leveraging templates, and will stay cloud native; this time depending on the functions Output ability to present the keys.

Azure IaC - Appending Tags

Dynamically appending Tags to our ARM template with the union function

Todays conundrum: As I am leveraging templates, there will always be some standard tags I require to implement within the template, but I also require to provide additional tags as a parameter to be appended with the deployment.

My objective is to set up tags within an ARM template in accordance with good governance and the Cloud adoption framework.