Azure Blueprints let you define repeatable sets of Azure resources that adhere to your governance standards.

Let’s see it in action. Imagine you need to deploy a new virtual network for a specific project, and this deployment must include a network security group (NSG) with specific inbound rules, a user-assigned managed identity for a future deployment, and a policy assignment to enforce tagging.

First, we define the blueprint. This is done in Azure portal, or via ARM templates. For this example, we’ll assume a blueprint named StandardNetworkDeployment with a version 1.0.0.

{
  "properties": {
    "description": "Standard network deployment with NSG, managed identity, and tagging policy.",
    "displayName": "Standard Network Deployment",
    "versions": {
      "1.0.0": {
        "description": "Initial version",
        "changeLog": [
          {
            "user": "admin",
            "message": "Created initial version."
          }
        ],
        "lastUpdatedDate": "2023-10-27T10:00:00Z",
        "blueprint": {
          "parameters": {
            "virtualNetworkName": {
              "type": "String",
              "defaultValue": "my-default-vnet",
              "metadata": {
                "displayName": "Virtual Network Name",
                "description": "Name of the virtual network."
              }
            },
            "resourceGroupName": {
              "type": "String",
              "defaultValue": "rg-network-standard",
              "metadata": {
                "displayName": "Resource Group Name",
                "description": "Name of the resource group for network resources."
              }
            }
          },
          "resourceGroups": {
            "rg-network-standard": {
              "metadata": {
                "displayName": "Network Resources"
              },
              "resources": [
                {
                  "type": "Microsoft.Network/virtualNetworks",
                  "apiVersion": "2020-11-01",
                  "name": "[parameters('virtualNetworkName')]",
                  "location": "[deployment().location]",
                  "properties": {
                    "addressSpace": {
                      "addressPrefixes": [
                        "10.0.0.0/16"
                      ]
                    }
                  }
                },
                {
                  "type": "Microsoft.Network/networkSecurityGroups",
                  "apiVersion": "2020-11-01",
                  "name": "nsg-standard",
                  "location": "[deployment().location]",
                  "properties": {
                    "securityRules": [
                      {
                        "name": "AllowRDP",
                        "properties": {
                          "priority": 100,
                          "access": "Allow",
                          "direction": "Inbound",
                          "protocol": "Tcp",
                          "sourcePortRange": "*",
                          "destinationPortRange": "3389",
                          "sourceAddressPrefix": "*",
                          "destinationAddressPrefix": "*"
                        }
                      }
                    ]
                  }
                }
              ]
            },
            "rg-identity-standard": {
              "metadata": {
                "displayName": "Identity Resources"
              },
              "resources": [
                {
                  "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
                  "apiVersion": "2018-11-30",
                  "name": "mi-standard-deployment",
                  "location": "[deployment().location]"
                }
              ]
            }
          },
          "roleAssignments": [],
          "policies": [
            {
              "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/4aa64879-a6c7-4761-a486-09345732563c",
              "parameters": {
                "tagName": {
                  "value": "ProjectCode"
                },
                "tagValue": {
                  "value": "XYZ"
                }
              },
              "enforcementMode": "DoNotEnforce"
            }
          ]
        }
      }
    }
  }
}

Now, we "publish" this blueprint. Once published, it’s available to be assigned.

To assign this blueprint to a subscription or resource group, you’d go to the Azure portal, find "Blueprints," select StandardNetworkDeployment v1.0.0, and click "Assign Blueprint."

You’ll provide a subscription, a name for the assignment (e.g., ProjectX-Network-Assignment), and then override or accept the default parameters. For instance, you might set virtualNetworkName to proj-x-vnet and resourceGroupName to rg-proj-x-network.

Upon assignment, Azure orchestrates the creation of the specified resources: a resource group named rg-proj-x-network containing a virtual network named proj-x-vnet and an NSG called nsg-standard. It also creates a separate resource group rg-identity-standard with the user-assigned managed identity mi-standard-deployment. Crucially, the policy assignment to enforce the ProjectCode: XYZ tag will be applied to the scope of the blueprint assignment.

The core problem Azure Blueprints solves is the drift from your established governance and compliance standards. Manually deploying resources often leads to inconsistencies, missed configurations, and security gaps. Blueprints provide a declarative, templated approach to ensure that every new environment or resource group starts from a known, compliant state. Think of it as infrastructure-as-code specifically for governance.

Behind the scenes, when you assign a blueprint, Azure translates the blueprint definition into ARM template deployments. It creates a "blueprint assignment" resource, which then triggers the underlying ARM deployments for each resource group, role assignment, and policy assignment defined within the blueprint. The enforcementMode in the policy assignment is particularly interesting: DoNotEnforce means the policy will audit compliance but won’t block non-compliant resource creation, whereas Enforce would block it. This allows for phased rollouts of stricter governance.

What most people miss is how Azure Blueprints handle updates. When you update a blueprint definition (e.g., change the NSG rules or add a new policy), it doesn’t automatically update existing assignments. You need to go to the specific blueprint assignment and "re-assign" it with the updated version or parameters. This explicit re-assignment is how Azure ensures you’re in control of applying changes to your deployed environments, preventing accidental widespread modifications.

The next logical step after mastering blueprint assignments is understanding how to create dynamic blueprint assignments using Azure Policy.

Want structured learning?

Take the full Azure course →