Create Azure Blueprints

The azure-native:blueprint:Blueprint resource, part of the Pulumi Azure Native provider, defines an Azure Blueprint: a reusable template that packages parameters, resource groups, and artifact definitions for consistent infrastructure deployment. This guide focuses on two capabilities: parameter definitions for customizable deployments and resource group placeholders with location and tags.

Blueprints are scoped to management groups or subscriptions via the resourceScope property. The examples are intentionally small. Combine them with blueprint artifacts (ARM templates, policies, role assignments) and assignment resources to deploy complete environments.

Define a blueprint with parameters and resource groups

Organizations standardizing infrastructure across subscriptions create blueprints at the management group level, defining parameters that assignments can customize and resource group placeholders that artifacts can target.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const blueprint = new azure_native.blueprint.Blueprint("blueprint", {
    blueprintName: "simpleBlueprint",
    description: "blueprint contains all artifact kinds {'template', 'rbac', 'policy'}",
    parameters: {
        costCenter: {
            displayName: "force cost center tag for all resources under given subscription.",
            type: azure_native.blueprint.TemplateParameterType.String,
        },
        owners: {
            displayName: "assign owners to subscription along with blueprint assignment.",
            type: azure_native.blueprint.TemplateParameterType.Array,
        },
        storageAccountType: {
            displayName: "storage account type.",
            type: azure_native.blueprint.TemplateParameterType.String,
        },
    },
    resourceGroups: {
        storageRG: {
            description: "Contains storageAccounts that collect all shoebox logs.",
            displayName: "storage resource group",
        },
    },
    resourceScope: "providers/Microsoft.Management/managementGroups/ContosoOnlineGroup",
    targetScope: azure_native.blueprint.BlueprintTargetScope.Subscription,
});
import pulumi
import pulumi_azure_native as azure_native

blueprint = azure_native.blueprint.Blueprint("blueprint",
    blueprint_name="simpleBlueprint",
    description="blueprint contains all artifact kinds {'template', 'rbac', 'policy'}",
    parameters={
        "costCenter": {
            "display_name": "force cost center tag for all resources under given subscription.",
            "type": azure_native.blueprint.TemplateParameterType.STRING,
        },
        "owners": {
            "display_name": "assign owners to subscription along with blueprint assignment.",
            "type": azure_native.blueprint.TemplateParameterType.ARRAY,
        },
        "storageAccountType": {
            "display_name": "storage account type.",
            "type": azure_native.blueprint.TemplateParameterType.STRING,
        },
    },
    resource_groups={
        "storageRG": {
            "description": "Contains storageAccounts that collect all shoebox logs.",
            "display_name": "storage resource group",
        },
    },
    resource_scope="providers/Microsoft.Management/managementGroups/ContosoOnlineGroup",
    target_scope=azure_native.blueprint.BlueprintTargetScope.SUBSCRIPTION)
package main

import (
	blueprint "github.com/pulumi/pulumi-azure-native-sdk/blueprint/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := blueprint.NewBlueprint(ctx, "blueprint", &blueprint.BlueprintArgs{
			BlueprintName: pulumi.String("simpleBlueprint"),
			Description:   pulumi.String("blueprint contains all artifact kinds {'template', 'rbac', 'policy'}"),
			Parameters: blueprint.ParameterDefinitionMap{
				"costCenter": &blueprint.ParameterDefinitionArgs{
					DisplayName: pulumi.String("force cost center tag for all resources under given subscription."),
					Type:        pulumi.String(blueprint.TemplateParameterTypeString),
				},
				"owners": &blueprint.ParameterDefinitionArgs{
					DisplayName: pulumi.String("assign owners to subscription along with blueprint assignment."),
					Type:        pulumi.String(blueprint.TemplateParameterTypeArray),
				},
				"storageAccountType": &blueprint.ParameterDefinitionArgs{
					DisplayName: pulumi.String("storage account type."),
					Type:        pulumi.String(blueprint.TemplateParameterTypeString),
				},
			},
			ResourceGroups: blueprint.ResourceGroupDefinitionMap{
				"storageRG": &blueprint.ResourceGroupDefinitionArgs{
					Description: pulumi.String("Contains storageAccounts that collect all shoebox logs."),
					DisplayName: pulumi.String("storage resource group"),
				},
			},
			ResourceScope: pulumi.String("providers/Microsoft.Management/managementGroups/ContosoOnlineGroup"),
			TargetScope:   pulumi.String(blueprint.BlueprintTargetScopeSubscription),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var blueprint = new AzureNative.Blueprint.Blueprint("blueprint", new()
    {
        BlueprintName = "simpleBlueprint",
        Description = "blueprint contains all artifact kinds {'template', 'rbac', 'policy'}",
        Parameters = 
        {
            { "costCenter", new AzureNative.Blueprint.Inputs.ParameterDefinitionArgs
            {
                DisplayName = "force cost center tag for all resources under given subscription.",
                Type = AzureNative.Blueprint.TemplateParameterType.@String,
            } },
            { "owners", new AzureNative.Blueprint.Inputs.ParameterDefinitionArgs
            {
                DisplayName = "assign owners to subscription along with blueprint assignment.",
                Type = AzureNative.Blueprint.TemplateParameterType.Array,
            } },
            { "storageAccountType", new AzureNative.Blueprint.Inputs.ParameterDefinitionArgs
            {
                DisplayName = "storage account type.",
                Type = AzureNative.Blueprint.TemplateParameterType.@String,
            } },
        },
        ResourceGroups = 
        {
            { "storageRG", new AzureNative.Blueprint.Inputs.ResourceGroupDefinitionArgs
            {
                Description = "Contains storageAccounts that collect all shoebox logs.",
                DisplayName = "storage resource group",
            } },
        },
        ResourceScope = "providers/Microsoft.Management/managementGroups/ContosoOnlineGroup",
        TargetScope = AzureNative.Blueprint.BlueprintTargetScope.Subscription,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.blueprint.Blueprint;
import com.pulumi.azurenative.blueprint.BlueprintArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var blueprint = new Blueprint("blueprint", BlueprintArgs.builder()
            .blueprintName("simpleBlueprint")
            .description("blueprint contains all artifact kinds {'template', 'rbac', 'policy'}")
            .parameters(Map.ofEntries(
                Map.entry("costCenter", ParameterDefinitionArgs.builder()
                    .displayName("force cost center tag for all resources under given subscription.")
                    .type("string")
                    .build()),
                Map.entry("owners", ParameterDefinitionArgs.builder()
                    .displayName("assign owners to subscription along with blueprint assignment.")
                    .type("array")
                    .build()),
                Map.entry("storageAccountType", ParameterDefinitionArgs.builder()
                    .displayName("storage account type.")
                    .type("string")
                    .build())
            ))
            .resourceGroups(Map.of("storageRG", ResourceGroupDefinitionArgs.builder()
                .description("Contains storageAccounts that collect all shoebox logs.")
                .displayName("storage resource group")
                .build()))
            .resourceScope("providers/Microsoft.Management/managementGroups/ContosoOnlineGroup")
            .targetScope("subscription")
            .build());

    }
}
resources:
  blueprint:
    type: azure-native:blueprint:Blueprint
    properties:
      blueprintName: simpleBlueprint
      description: blueprint contains all artifact kinds {'template', 'rbac', 'policy'}
      parameters:
        costCenter:
          displayName: force cost center tag for all resources under given subscription.
          type: string
        owners:
          displayName: assign owners to subscription along with blueprint assignment.
          type: array
        storageAccountType:
          displayName: storage account type.
          type: string
      resourceGroups:
        storageRG:
          description: Contains storageAccounts that collect all shoebox logs.
          displayName: storage resource group
      resourceScope: providers/Microsoft.Management/managementGroups/ContosoOnlineGroup
      targetScope: subscription

The parameters property defines inputs that blueprint assignments must provide. Each parameter specifies a type (string, array, object) and displayName for documentation. The resourceGroups property creates named placeholders that artifacts reference when deploying resources. The resourceScope determines where the blueprint definition lives (management group or subscription), while targetScope specifies where assignments can occur.

Configure resource groups with location and tags

Blueprints can pre-configure resource groups with specific locations and tags, ensuring consistent metadata and placement across all assignments.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const blueprint = new azure_native.blueprint.Blueprint("blueprint", {
    blueprintName: "simpleBlueprint",
    description: "An example blueprint containing an RG with two tags.",
    resourceGroups: {
        myRGName: {
            displayName: "My Resource Group",
            location: "westus",
            name: "myRGName",
            tags: {
                costcenter: "123456",
                nameOnlyTag: "",
            },
        },
    },
    resourceScope: "providers/Microsoft.Management/managementGroups/{ManagementGroupId}",
    targetScope: azure_native.blueprint.BlueprintTargetScope.Subscription,
});
import pulumi
import pulumi_azure_native as azure_native

blueprint = azure_native.blueprint.Blueprint("blueprint",
    blueprint_name="simpleBlueprint",
    description="An example blueprint containing an RG with two tags.",
    resource_groups={
        "myRGName": {
            "display_name": "My Resource Group",
            "location": "westus",
            "name": "myRGName",
            "tags": {
                "costcenter": "123456",
                "nameOnlyTag": "",
            },
        },
    },
    resource_scope="providers/Microsoft.Management/managementGroups/{ManagementGroupId}",
    target_scope=azure_native.blueprint.BlueprintTargetScope.SUBSCRIPTION)
package main

import (
	blueprint "github.com/pulumi/pulumi-azure-native-sdk/blueprint/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := blueprint.NewBlueprint(ctx, "blueprint", &blueprint.BlueprintArgs{
			BlueprintName: pulumi.String("simpleBlueprint"),
			Description:   pulumi.String("An example blueprint containing an RG with two tags."),
			ResourceGroups: blueprint.ResourceGroupDefinitionMap{
				"myRGName": &blueprint.ResourceGroupDefinitionArgs{
					DisplayName: pulumi.String("My Resource Group"),
					Location:    pulumi.String("westus"),
					Name:        pulumi.String("myRGName"),
					Tags: pulumi.StringMap{
						"costcenter":  pulumi.String("123456"),
						"nameOnlyTag": pulumi.String(""),
					},
				},
			},
			ResourceScope: pulumi.String("providers/Microsoft.Management/managementGroups/{ManagementGroupId}"),
			TargetScope:   pulumi.String(blueprint.BlueprintTargetScopeSubscription),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var blueprint = new AzureNative.Blueprint.Blueprint("blueprint", new()
    {
        BlueprintName = "simpleBlueprint",
        Description = "An example blueprint containing an RG with two tags.",
        ResourceGroups = 
        {
            { "myRGName", new AzureNative.Blueprint.Inputs.ResourceGroupDefinitionArgs
            {
                DisplayName = "My Resource Group",
                Location = "westus",
                Name = "myRGName",
                Tags = 
                {
                    { "costcenter", "123456" },
                    { "nameOnlyTag", "" },
                },
            } },
        },
        ResourceScope = "providers/Microsoft.Management/managementGroups/{ManagementGroupId}",
        TargetScope = AzureNative.Blueprint.BlueprintTargetScope.Subscription,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.blueprint.Blueprint;
import com.pulumi.azurenative.blueprint.BlueprintArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var blueprint = new Blueprint("blueprint", BlueprintArgs.builder()
            .blueprintName("simpleBlueprint")
            .description("An example blueprint containing an RG with two tags.")
            .resourceGroups(Map.of("myRGName", ResourceGroupDefinitionArgs.builder()
                .displayName("My Resource Group")
                .location("westus")
                .name("myRGName")
                .tags(Map.ofEntries(
                    Map.entry("costcenter", "123456"),
                    Map.entry("nameOnlyTag", "")
                ))
                .build()))
            .resourceScope("providers/Microsoft.Management/managementGroups/{ManagementGroupId}")
            .targetScope("subscription")
            .build());

    }
}
resources:
  blueprint:
    type: azure-native:blueprint:Blueprint
    properties:
      blueprintName: simpleBlueprint
      description: An example blueprint containing an RG with two tags.
      resourceGroups:
        myRGName:
          displayName: My Resource Group
          location: westus
          name: myRGName
          tags:
            costcenter: '123456'
            nameOnlyTag: ""
      resourceScope: providers/Microsoft.Management/managementGroups/{ManagementGroupId}
      targetScope: subscription

Resource group definitions can specify location to control regional placement and tags to enforce organizational metadata. The name property sets the resource group name at assignment time. Tags support both key-value pairs and name-only tags (empty string values).

Beyond these examples

These snippets focus on specific blueprint definition features: parameter definitions for customizable deployments and resource group placeholders with location and tags. They’re intentionally minimal rather than full governance solutions.

The examples reference pre-existing infrastructure such as management groups or subscriptions via resourceScope targets. They focus on defining the blueprint structure rather than provisioning artifacts or assignments.

To keep things focused, common blueprint patterns are omitted, including:

  • Blueprint artifacts (ARM templates, policy assignments, role assignments)
  • Blueprint versions and publishing workflow
  • Blueprint assignments to subscriptions
  • Parameter constraints (allowedValues, defaultValue)

These omissions are intentional: the goal is to illustrate how blueprint definitions are structured, not provide drop-in governance modules. See the Blueprint resource reference for all available configuration options.

Let's create Azure Blueprints

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Scope & Targeting
What's the difference between resourceScope and targetScope?
resourceScope defines where the blueprint definition is stored (management group or subscription), while targetScope specifies where the blueprint can be assigned (e.g., subscription).
What are the valid formats for resourceScope?
Use management group format /providers/Microsoft.Management/managementGroups/{managementGroup} or subscription format /subscriptions/{subscriptionId}.
What properties can't I change after creating a blueprint?
Both blueprintName and resourceScope are immutable and require resource replacement if changed.
Blueprint Configuration
What parameter types can I use in blueprint definitions?
Blueprint parameters support types like string and array, each with a displayName and type property.
How do I define resource groups in a blueprint?
Use the resourceGroups property with a map of resource group definitions that can include description, displayName, location, name, and tags.
Can I use tags with empty values in resource group definitions?
Yes, you can specify tags with empty string values, as shown in the nameOnlyTag example.
What API version does this resource use?
The resource uses Azure REST API version 2018-11-01-preview.

Using a different cloud?

Explore integration guides for other cloud providers: