Configure Azure Policy Assignments

The azure-native:authorization:PolicyAssignment resource, part of the Pulumi Azure Native provider, links Azure Policy definitions to scopes and configures their behavior through parameters, enforcement modes, and conditional logic. This guide focuses on three capabilities: assigning policies with parameters, enabling managed identities for remediation, and customizing behavior with overrides and resource selectors.

Policy assignments reference existing policy definitions or policy sets and target Azure scopes that must already exist. The examples are intentionally small. Combine them with your own policy definitions, RBAC role assignments, and organizational scope structure.

Assign a policy with parameters and compliance messages

Organizations enforce governance rules by assigning policies to subscriptions, resource groups, or management groups, providing parameter values that customize the policy’s behavior.

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

const policyAssignment = new azure_native.authorization.PolicyAssignment("policyAssignment", {
    description: "Force resource names to begin with given DeptA and end with -LC",
    displayName: "Enforce resource naming rules",
    metadata: {
        assignedBy: "Special Someone",
    },
    nonComplianceMessages: [{
        message: "Resource names must start with 'DeptA' and end with '-LC'.",
    }],
    parameters: {
        prefix: {
            value: "DeptA",
        },
        suffix: {
            value: "-LC",
        },
    },
    policyAssignmentName: "EnforceNaming",
    policyDefinitionId: "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming",
    scope: "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
});
import pulumi
import pulumi_azure_native as azure_native

policy_assignment = azure_native.authorization.PolicyAssignment("policyAssignment",
    description="Force resource names to begin with given DeptA and end with -LC",
    display_name="Enforce resource naming rules",
    metadata={
        "assignedBy": "Special Someone",
    },
    non_compliance_messages=[{
        "message": "Resource names must start with 'DeptA' and end with '-LC'.",
    }],
    parameters={
        "prefix": {
            "value": "DeptA",
        },
        "suffix": {
            "value": "-LC",
        },
    },
    policy_assignment_name="EnforceNaming",
    policy_definition_id="/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming",
    scope="subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := authorization.NewPolicyAssignment(ctx, "policyAssignment", &authorization.PolicyAssignmentArgs{
			Description: pulumi.String("Force resource names to begin with given DeptA and end with -LC"),
			DisplayName: pulumi.String("Enforce resource naming rules"),
			Metadata: pulumi.Any(map[string]interface{}{
				"assignedBy": "Special Someone",
			}),
			NonComplianceMessages: authorization.NonComplianceMessageArray{
				&authorization.NonComplianceMessageArgs{
					Message: pulumi.String("Resource names must start with 'DeptA' and end with '-LC'."),
				},
			},
			Parameters: authorization.ParameterValuesValueMap{
				"prefix": &authorization.ParameterValuesValueArgs{
					Value: pulumi.Any("DeptA"),
				},
				"suffix": &authorization.ParameterValuesValueArgs{
					Value: pulumi.Any("-LC"),
				},
			},
			PolicyAssignmentName: pulumi.String("EnforceNaming"),
			PolicyDefinitionId:   pulumi.String("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming"),
			Scope:                pulumi.String("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2"),
		})
		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 policyAssignment = new AzureNative.Authorization.PolicyAssignment("policyAssignment", new()
    {
        Description = "Force resource names to begin with given DeptA and end with -LC",
        DisplayName = "Enforce resource naming rules",
        Metadata = new Dictionary<string, object?>
        {
            ["assignedBy"] = "Special Someone",
        },
        NonComplianceMessages = new[]
        {
            new AzureNative.Authorization.Inputs.NonComplianceMessageArgs
            {
                Message = "Resource names must start with 'DeptA' and end with '-LC'.",
            },
        },
        Parameters = 
        {
            { "prefix", new AzureNative.Authorization.Inputs.ParameterValuesValueArgs
            {
                Value = "DeptA",
            } },
            { "suffix", new AzureNative.Authorization.Inputs.ParameterValuesValueArgs
            {
                Value = "-LC",
            } },
        },
        PolicyAssignmentName = "EnforceNaming",
        PolicyDefinitionId = "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming",
        Scope = "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.PolicyAssignment;
import com.pulumi.azurenative.authorization.PolicyAssignmentArgs;
import com.pulumi.azurenative.authorization.inputs.NonComplianceMessageArgs;
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 policyAssignment = new PolicyAssignment("policyAssignment", PolicyAssignmentArgs.builder()
            .description("Force resource names to begin with given DeptA and end with -LC")
            .displayName("Enforce resource naming rules")
            .metadata(Map.of("assignedBy", "Special Someone"))
            .nonComplianceMessages(NonComplianceMessageArgs.builder()
                .message("Resource names must start with 'DeptA' and end with '-LC'.")
                .build())
            .parameters(Map.ofEntries(
                Map.entry("prefix", ParameterValuesValueArgs.builder()
                    .value("DeptA")
                    .build()),
                Map.entry("suffix", ParameterValuesValueArgs.builder()
                    .value("-LC")
                    .build())
            ))
            .policyAssignmentName("EnforceNaming")
            .policyDefinitionId("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming")
            .scope("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
            .build());

    }
}
resources:
  policyAssignment:
    type: azure-native:authorization:PolicyAssignment
    properties:
      description: Force resource names to begin with given DeptA and end with -LC
      displayName: Enforce resource naming rules
      metadata:
        assignedBy: Special Someone
      nonComplianceMessages:
        - message: Resource names must start with 'DeptA' and end with '-LC'.
      parameters:
        prefix:
          value: DeptA
        suffix:
          value: -LC
      policyAssignmentName: EnforceNaming
      policyDefinitionId: /subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming
      scope: subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2

The policyDefinitionId references the policy to enforce, while scope determines where it applies (subscription, resource group, or management group). The parameters property passes values to the policy’s parameter definitions. The nonComplianceMessages array provides custom error messages when resources violate the policy, helping teams understand what went wrong.

Enable managed identity for policy remediation

Policies with DeployIfNotExists or Modify effects need permissions to create or modify resources. System-assigned managed identities provide these permissions without managing service principals.

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

const policyAssignment = new azure_native.authorization.PolicyAssignment("policyAssignment", {
    description: "Force resource names to begin with given DeptA and end with -LC",
    displayName: "Enforce resource naming rules",
    enforcementMode: azure_native.authorization.EnforcementMode.Default,
    identity: {
        type: azure_native.authorization.ResourceIdentityType.SystemAssigned,
    },
    location: "eastus",
    metadata: {
        assignedBy: "Foo Bar",
    },
    parameters: {
        prefix: {
            value: "DeptA",
        },
        suffix: {
            value: "-LC",
        },
    },
    policyAssignmentName: "EnforceNaming",
    policyDefinitionId: "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming",
    scope: "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
});
import pulumi
import pulumi_azure_native as azure_native

policy_assignment = azure_native.authorization.PolicyAssignment("policyAssignment",
    description="Force resource names to begin with given DeptA and end with -LC",
    display_name="Enforce resource naming rules",
    enforcement_mode=azure_native.authorization.EnforcementMode.DEFAULT,
    identity={
        "type": azure_native.authorization.ResourceIdentityType.SYSTEM_ASSIGNED,
    },
    location="eastus",
    metadata={
        "assignedBy": "Foo Bar",
    },
    parameters={
        "prefix": {
            "value": "DeptA",
        },
        "suffix": {
            "value": "-LC",
        },
    },
    policy_assignment_name="EnforceNaming",
    policy_definition_id="/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming",
    scope="subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := authorization.NewPolicyAssignment(ctx, "policyAssignment", &authorization.PolicyAssignmentArgs{
			Description:     pulumi.String("Force resource names to begin with given DeptA and end with -LC"),
			DisplayName:     pulumi.String("Enforce resource naming rules"),
			EnforcementMode: pulumi.String(authorization.EnforcementModeDefault),
			Identity: &authorization.IdentityArgs{
				Type: authorization.ResourceIdentityTypeSystemAssigned,
			},
			Location: pulumi.String("eastus"),
			Metadata: pulumi.Any(map[string]interface{}{
				"assignedBy": "Foo Bar",
			}),
			Parameters: authorization.ParameterValuesValueMap{
				"prefix": &authorization.ParameterValuesValueArgs{
					Value: pulumi.Any("DeptA"),
				},
				"suffix": &authorization.ParameterValuesValueArgs{
					Value: pulumi.Any("-LC"),
				},
			},
			PolicyAssignmentName: pulumi.String("EnforceNaming"),
			PolicyDefinitionId:   pulumi.String("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming"),
			Scope:                pulumi.String("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2"),
		})
		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 policyAssignment = new AzureNative.Authorization.PolicyAssignment("policyAssignment", new()
    {
        Description = "Force resource names to begin with given DeptA and end with -LC",
        DisplayName = "Enforce resource naming rules",
        EnforcementMode = AzureNative.Authorization.EnforcementMode.Default,
        Identity = new AzureNative.Authorization.Inputs.IdentityArgs
        {
            Type = AzureNative.Authorization.ResourceIdentityType.SystemAssigned,
        },
        Location = "eastus",
        Metadata = new Dictionary<string, object?>
        {
            ["assignedBy"] = "Foo Bar",
        },
        Parameters = 
        {
            { "prefix", new AzureNative.Authorization.Inputs.ParameterValuesValueArgs
            {
                Value = "DeptA",
            } },
            { "suffix", new AzureNative.Authorization.Inputs.ParameterValuesValueArgs
            {
                Value = "-LC",
            } },
        },
        PolicyAssignmentName = "EnforceNaming",
        PolicyDefinitionId = "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming",
        Scope = "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.PolicyAssignment;
import com.pulumi.azurenative.authorization.PolicyAssignmentArgs;
import com.pulumi.azurenative.authorization.inputs.IdentityArgs;
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 policyAssignment = new PolicyAssignment("policyAssignment", PolicyAssignmentArgs.builder()
            .description("Force resource names to begin with given DeptA and end with -LC")
            .displayName("Enforce resource naming rules")
            .enforcementMode("Default")
            .identity(IdentityArgs.builder()
                .type("SystemAssigned")
                .build())
            .location("eastus")
            .metadata(Map.of("assignedBy", "Foo Bar"))
            .parameters(Map.ofEntries(
                Map.entry("prefix", ParameterValuesValueArgs.builder()
                    .value("DeptA")
                    .build()),
                Map.entry("suffix", ParameterValuesValueArgs.builder()
                    .value("-LC")
                    .build())
            ))
            .policyAssignmentName("EnforceNaming")
            .policyDefinitionId("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming")
            .scope("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
            .build());

    }
}
resources:
  policyAssignment:
    type: azure-native:authorization:PolicyAssignment
    properties:
      description: Force resource names to begin with given DeptA and end with -LC
      displayName: Enforce resource naming rules
      enforcementMode: Default
      identity:
        type: SystemAssigned
      location: eastus
      metadata:
        assignedBy: Foo Bar
      parameters:
        prefix:
          value: DeptA
        suffix:
          value: -LC
      policyAssignmentName: EnforceNaming
      policyDefinitionId: /subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policyDefinitions/ResourceNaming
      scope: subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2

When identity is configured with type SystemAssigned, Azure creates a managed identity for the assignment. The location property is required when using managed identities. The enforcementMode controls whether the policy actively blocks non-compliant operations (Default) or only audits them. After creating the assignment, you must grant the identity appropriate RBAC roles to perform remediation actions.

Provide targeted messages for policy set violations

Policy sets bundle multiple policies together. When resources violate specific policies within the set, targeted messages help teams understand which requirement failed.

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

const policyAssignment = new azure_native.authorization.PolicyAssignment("policyAssignment", {
    displayName: "Enforce security policies",
    nonComplianceMessages: [
        {
            message: "Resources must comply with all internal security policies. See <internal site URL> for more info.",
        },
        {
            message: "Resource names must start with 'DeptA' and end with '-LC'.",
            policyDefinitionReferenceId: "10420126870854049575",
        },
        {
            message: "Storage accounts must have firewall rules configured.",
            policyDefinitionReferenceId: "8572513655450389710",
        },
    ],
    policyAssignmentName: "securityInitAssignment",
    policyDefinitionId: "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/securityInitiative",
    scope: "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
});
import pulumi
import pulumi_azure_native as azure_native

policy_assignment = azure_native.authorization.PolicyAssignment("policyAssignment",
    display_name="Enforce security policies",
    non_compliance_messages=[
        {
            "message": "Resources must comply with all internal security policies. See <internal site URL> for more info.",
        },
        {
            "message": "Resource names must start with 'DeptA' and end with '-LC'.",
            "policy_definition_reference_id": "10420126870854049575",
        },
        {
            "message": "Storage accounts must have firewall rules configured.",
            "policy_definition_reference_id": "8572513655450389710",
        },
    ],
    policy_assignment_name="securityInitAssignment",
    policy_definition_id="/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/securityInitiative",
    scope="subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := authorization.NewPolicyAssignment(ctx, "policyAssignment", &authorization.PolicyAssignmentArgs{
			DisplayName: pulumi.String("Enforce security policies"),
			NonComplianceMessages: authorization.NonComplianceMessageArray{
				&authorization.NonComplianceMessageArgs{
					Message: pulumi.String("Resources must comply with all internal security policies. See <internal site URL> for more info."),
				},
				&authorization.NonComplianceMessageArgs{
					Message:                     pulumi.String("Resource names must start with 'DeptA' and end with '-LC'."),
					PolicyDefinitionReferenceId: pulumi.String("10420126870854049575"),
				},
				&authorization.NonComplianceMessageArgs{
					Message:                     pulumi.String("Storage accounts must have firewall rules configured."),
					PolicyDefinitionReferenceId: pulumi.String("8572513655450389710"),
				},
			},
			PolicyAssignmentName: pulumi.String("securityInitAssignment"),
			PolicyDefinitionId:   pulumi.String("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/securityInitiative"),
			Scope:                pulumi.String("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2"),
		})
		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 policyAssignment = new AzureNative.Authorization.PolicyAssignment("policyAssignment", new()
    {
        DisplayName = "Enforce security policies",
        NonComplianceMessages = new[]
        {
            new AzureNative.Authorization.Inputs.NonComplianceMessageArgs
            {
                Message = "Resources must comply with all internal security policies. See <internal site URL> for more info.",
            },
            new AzureNative.Authorization.Inputs.NonComplianceMessageArgs
            {
                Message = "Resource names must start with 'DeptA' and end with '-LC'.",
                PolicyDefinitionReferenceId = "10420126870854049575",
            },
            new AzureNative.Authorization.Inputs.NonComplianceMessageArgs
            {
                Message = "Storage accounts must have firewall rules configured.",
                PolicyDefinitionReferenceId = "8572513655450389710",
            },
        },
        PolicyAssignmentName = "securityInitAssignment",
        PolicyDefinitionId = "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/securityInitiative",
        Scope = "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.PolicyAssignment;
import com.pulumi.azurenative.authorization.PolicyAssignmentArgs;
import com.pulumi.azurenative.authorization.inputs.NonComplianceMessageArgs;
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 policyAssignment = new PolicyAssignment("policyAssignment", PolicyAssignmentArgs.builder()
            .displayName("Enforce security policies")
            .nonComplianceMessages(            
                NonComplianceMessageArgs.builder()
                    .message("Resources must comply with all internal security policies. See <internal site URL> for more info.")
                    .build(),
                NonComplianceMessageArgs.builder()
                    .message("Resource names must start with 'DeptA' and end with '-LC'.")
                    .policyDefinitionReferenceId("10420126870854049575")
                    .build(),
                NonComplianceMessageArgs.builder()
                    .message("Storage accounts must have firewall rules configured.")
                    .policyDefinitionReferenceId("8572513655450389710")
                    .build())
            .policyAssignmentName("securityInitAssignment")
            .policyDefinitionId("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/securityInitiative")
            .scope("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
            .build());

    }
}
resources:
  policyAssignment:
    type: azure-native:authorization:PolicyAssignment
    properties:
      displayName: Enforce security policies
      nonComplianceMessages:
        - message: Resources must comply with all internal security policies. See <internal site URL> for more info.
        - message: Resource names must start with 'DeptA' and end with '-LC'.
          policyDefinitionReferenceId: '10420126870854049575'
        - message: Storage accounts must have firewall rules configured.
          policyDefinitionReferenceId: '8572513655450389710'
      policyAssignmentName: securityInitAssignment
      policyDefinitionId: /subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/securityInitiative
      scope: subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2

The nonComplianceMessages array can include multiple entries. Messages without a policyDefinitionReferenceId apply to the entire assignment. Messages with a policyDefinitionReferenceId target specific policies within a policy set, providing context about which rule was violated. The reference IDs come from the policy set definition itself.

Override policy effects and versions conditionally

Large organizations often need different policy behavior across regions or resource types. Overrides let you change policy effects or definition versions for specific selectors without creating separate assignments.

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

const policyAssignment = new azure_native.authorization.PolicyAssignment("policyAssignment", {
    definitionVersion: "1.*.*",
    description: "Limit the resource location and resource SKU",
    displayName: "Limit the resource location and resource SKU",
    metadata: {
        assignedBy: "Special Someone",
    },
    overrides: [
        {
            kind: azure_native.authorization.OverrideKind.PolicyEffect,
            selectors: [{
                "in": [
                    "Limit_Skus",
                    "Limit_Locations",
                ],
                kind: azure_native.authorization.SelectorKind.PolicyDefinitionReferenceId,
            }],
            value: "Audit",
        },
        {
            kind: azure_native.authorization.OverrideKind.DefinitionVersion,
            selectors: [{
                "in": [
                    "eastUSEuap",
                    "centralUSEuap",
                ],
                kind: azure_native.authorization.SelectorKind.ResourceLocation,
            }],
            value: "2.*.*",
        },
    ],
    policyAssignmentName: "CostManagement",
    policyDefinitionId: "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement",
    scope: "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
});
import pulumi
import pulumi_azure_native as azure_native

policy_assignment = azure_native.authorization.PolicyAssignment("policyAssignment",
    definition_version="1.*.*",
    description="Limit the resource location and resource SKU",
    display_name="Limit the resource location and resource SKU",
    metadata={
        "assignedBy": "Special Someone",
    },
    overrides=[
        {
            "kind": azure_native.authorization.OverrideKind.POLICY_EFFECT,
            "selectors": [{
                "in_": [
                    "Limit_Skus",
                    "Limit_Locations",
                ],
                "kind": azure_native.authorization.SelectorKind.POLICY_DEFINITION_REFERENCE_ID,
            }],
            "value": "Audit",
        },
        {
            "kind": azure_native.authorization.OverrideKind.DEFINITION_VERSION,
            "selectors": [{
                "in_": [
                    "eastUSEuap",
                    "centralUSEuap",
                ],
                "kind": azure_native.authorization.SelectorKind.RESOURCE_LOCATION,
            }],
            "value": "2.*.*",
        },
    ],
    policy_assignment_name="CostManagement",
    policy_definition_id="/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement",
    scope="subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := authorization.NewPolicyAssignment(ctx, "policyAssignment", &authorization.PolicyAssignmentArgs{
			DefinitionVersion: pulumi.String("1.*.*"),
			Description:       pulumi.String("Limit the resource location and resource SKU"),
			DisplayName:       pulumi.String("Limit the resource location and resource SKU"),
			Metadata: pulumi.Any(map[string]interface{}{
				"assignedBy": "Special Someone",
			}),
			Overrides: authorization.OverrideArray{
				&authorization.OverrideArgs{
					Kind: pulumi.String(authorization.OverrideKindPolicyEffect),
					Selectors: authorization.SelectorArray{
						&authorization.SelectorArgs{
							In: pulumi.StringArray{
								pulumi.String("Limit_Skus"),
								pulumi.String("Limit_Locations"),
							},
							Kind: pulumi.String(authorization.SelectorKindPolicyDefinitionReferenceId),
						},
					},
					Value: pulumi.String("Audit"),
				},
				&authorization.OverrideArgs{
					Kind: pulumi.String(authorization.OverrideKindDefinitionVersion),
					Selectors: authorization.SelectorArray{
						&authorization.SelectorArgs{
							In: pulumi.StringArray{
								pulumi.String("eastUSEuap"),
								pulumi.String("centralUSEuap"),
							},
							Kind: pulumi.String(authorization.SelectorKindResourceLocation),
						},
					},
					Value: pulumi.String("2.*.*"),
				},
			},
			PolicyAssignmentName: pulumi.String("CostManagement"),
			PolicyDefinitionId:   pulumi.String("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement"),
			Scope:                pulumi.String("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2"),
		})
		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 policyAssignment = new AzureNative.Authorization.PolicyAssignment("policyAssignment", new()
    {
        DefinitionVersion = "1.*.*",
        Description = "Limit the resource location and resource SKU",
        DisplayName = "Limit the resource location and resource SKU",
        Metadata = new Dictionary<string, object?>
        {
            ["assignedBy"] = "Special Someone",
        },
        Overrides = new[]
        {
            new AzureNative.Authorization.Inputs.OverrideArgs
            {
                Kind = AzureNative.Authorization.OverrideKind.PolicyEffect,
                Selectors = new[]
                {
                    new AzureNative.Authorization.Inputs.SelectorArgs
                    {
                        In = new[]
                        {
                            "Limit_Skus",
                            "Limit_Locations",
                        },
                        Kind = AzureNative.Authorization.SelectorKind.PolicyDefinitionReferenceId,
                    },
                },
                Value = "Audit",
            },
            new AzureNative.Authorization.Inputs.OverrideArgs
            {
                Kind = AzureNative.Authorization.OverrideKind.DefinitionVersion,
                Selectors = new[]
                {
                    new AzureNative.Authorization.Inputs.SelectorArgs
                    {
                        In = new[]
                        {
                            "eastUSEuap",
                            "centralUSEuap",
                        },
                        Kind = AzureNative.Authorization.SelectorKind.ResourceLocation,
                    },
                },
                Value = "2.*.*",
            },
        },
        PolicyAssignmentName = "CostManagement",
        PolicyDefinitionId = "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement",
        Scope = "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.PolicyAssignment;
import com.pulumi.azurenative.authorization.PolicyAssignmentArgs;
import com.pulumi.azurenative.authorization.inputs.OverrideArgs;
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 policyAssignment = new PolicyAssignment("policyAssignment", PolicyAssignmentArgs.builder()
            .definitionVersion("1.*.*")
            .description("Limit the resource location and resource SKU")
            .displayName("Limit the resource location and resource SKU")
            .metadata(Map.of("assignedBy", "Special Someone"))
            .overrides(            
                OverrideArgs.builder()
                    .kind("policyEffect")
                    .selectors(SelectorArgs.builder()
                        .in(                        
                            "Limit_Skus",
                            "Limit_Locations")
                        .kind("policyDefinitionReferenceId")
                        .build())
                    .value("Audit")
                    .build(),
                OverrideArgs.builder()
                    .kind("definitionVersion")
                    .selectors(SelectorArgs.builder()
                        .in(                        
                            "eastUSEuap",
                            "centralUSEuap")
                        .kind("resourceLocation")
                        .build())
                    .value("2.*.*")
                    .build())
            .policyAssignmentName("CostManagement")
            .policyDefinitionId("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement")
            .scope("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
            .build());

    }
}
resources:
  policyAssignment:
    type: azure-native:authorization:PolicyAssignment
    properties:
      definitionVersion: 1.*.*
      description: Limit the resource location and resource SKU
      displayName: Limit the resource location and resource SKU
      metadata:
        assignedBy: Special Someone
      overrides:
        - kind: policyEffect
          selectors:
            - in:
                - Limit_Skus
                - Limit_Locations
              kind: policyDefinitionReferenceId
          value: Audit
        - kind: definitionVersion
          selectors:
            - in:
                - eastUSEuap
                - centralUSEuap
              kind: resourceLocation
          value: 2.*.*
      policyAssignmentName: CostManagement
      policyDefinitionId: /subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement
      scope: subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2

The overrides array modifies policy behavior based on selectors. Each override specifies a kind (policyEffect or definitionVersion) and a value to apply. The selectors array filters which policies or resources the override affects. In this configuration, the first override changes the effect to Audit for specific policy definitions, while the second override uses a different definition version for resources in specific regions.

Scope policy evaluation to specific resource locations

Resource selectors filter which resources the policy evaluates based on location, type, or other attributes, providing finer control than scope alone.

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

const policyAssignment = new azure_native.authorization.PolicyAssignment("policyAssignment", {
    description: "Limit the resource location and resource SKU",
    displayName: "Limit the resource location and resource SKU",
    metadata: {
        assignedBy: "Special Someone",
    },
    policyAssignmentName: "CostManagement",
    policyDefinitionId: "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement",
    resourceSelectors: [{
        name: "SDPRegions",
        selectors: [{
            "in": [
                "eastus2euap",
                "centraluseuap",
            ],
            kind: azure_native.authorization.SelectorKind.ResourceLocation,
        }],
    }],
    scope: "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
});
import pulumi
import pulumi_azure_native as azure_native

policy_assignment = azure_native.authorization.PolicyAssignment("policyAssignment",
    description="Limit the resource location and resource SKU",
    display_name="Limit the resource location and resource SKU",
    metadata={
        "assignedBy": "Special Someone",
    },
    policy_assignment_name="CostManagement",
    policy_definition_id="/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement",
    resource_selectors=[{
        "name": "SDPRegions",
        "selectors": [{
            "in_": [
                "eastus2euap",
                "centraluseuap",
            ],
            "kind": azure_native.authorization.SelectorKind.RESOURCE_LOCATION,
        }],
    }],
    scope="subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := authorization.NewPolicyAssignment(ctx, "policyAssignment", &authorization.PolicyAssignmentArgs{
			Description: pulumi.String("Limit the resource location and resource SKU"),
			DisplayName: pulumi.String("Limit the resource location and resource SKU"),
			Metadata: pulumi.Any(map[string]interface{}{
				"assignedBy": "Special Someone",
			}),
			PolicyAssignmentName: pulumi.String("CostManagement"),
			PolicyDefinitionId:   pulumi.String("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement"),
			ResourceSelectors: authorization.ResourceSelectorArray{
				&authorization.ResourceSelectorArgs{
					Name: pulumi.String("SDPRegions"),
					Selectors: authorization.SelectorArray{
						&authorization.SelectorArgs{
							In: pulumi.StringArray{
								pulumi.String("eastus2euap"),
								pulumi.String("centraluseuap"),
							},
							Kind: pulumi.String(authorization.SelectorKindResourceLocation),
						},
					},
				},
			},
			Scope: pulumi.String("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2"),
		})
		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 policyAssignment = new AzureNative.Authorization.PolicyAssignment("policyAssignment", new()
    {
        Description = "Limit the resource location and resource SKU",
        DisplayName = "Limit the resource location and resource SKU",
        Metadata = new Dictionary<string, object?>
        {
            ["assignedBy"] = "Special Someone",
        },
        PolicyAssignmentName = "CostManagement",
        PolicyDefinitionId = "/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement",
        ResourceSelectors = new[]
        {
            new AzureNative.Authorization.Inputs.ResourceSelectorArgs
            {
                Name = "SDPRegions",
                Selectors = new[]
                {
                    new AzureNative.Authorization.Inputs.SelectorArgs
                    {
                        In = new[]
                        {
                            "eastus2euap",
                            "centraluseuap",
                        },
                        Kind = AzureNative.Authorization.SelectorKind.ResourceLocation,
                    },
                },
            },
        },
        Scope = "subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.PolicyAssignment;
import com.pulumi.azurenative.authorization.PolicyAssignmentArgs;
import com.pulumi.azurenative.authorization.inputs.ResourceSelectorArgs;
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 policyAssignment = new PolicyAssignment("policyAssignment", PolicyAssignmentArgs.builder()
            .description("Limit the resource location and resource SKU")
            .displayName("Limit the resource location and resource SKU")
            .metadata(Map.of("assignedBy", "Special Someone"))
            .policyAssignmentName("CostManagement")
            .policyDefinitionId("/subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement")
            .resourceSelectors(ResourceSelectorArgs.builder()
                .name("SDPRegions")
                .selectors(SelectorArgs.builder()
                    .in(                    
                        "eastus2euap",
                        "centraluseuap")
                    .kind("resourceLocation")
                    .build())
                .build())
            .scope("subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2")
            .build());

    }
}
resources:
  policyAssignment:
    type: azure-native:authorization:PolicyAssignment
    properties:
      description: Limit the resource location and resource SKU
      displayName: Limit the resource location and resource SKU
      metadata:
        assignedBy: Special Someone
      policyAssignmentName: CostManagement
      policyDefinitionId: /subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2/providers/Microsoft.Authorization/policySetDefinitions/CostManagement
      resourceSelectors:
        - name: SDPRegions
          selectors:
            - in:
                - eastus2euap
                - centraluseuap
              kind: resourceLocation
      scope: subscriptions/ae640e6b-ba3e-4256-9d62-2993eecfa6f2

The resourceSelectors array defines named filter sets. Each selector contains a kind (resourceLocation, resourceType, or resourceWithoutLocation) and an in array listing values to match. When resource selectors are present, the policy only evaluates resources that match at least one selector. This lets you apply policies to specific regions without creating multiple assignments.

Beyond these examples

These snippets focus on specific policy assignment features: policy assignment with parameters and compliance messages, managed identity for remediation, and overrides and resource selectors for conditional behavior. They’re intentionally minimal rather than full governance frameworks.

The examples reference pre-existing infrastructure such as policy definitions or policy set definitions, and Azure subscriptions, resource groups, or management groups for scope. They focus on configuring the assignment rather than creating the underlying policies or RBAC roles.

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

  • Enforcement mode variations (Default, DoNotEnforce, Enroll)
  • Exclusion scopes (notScopes)
  • User-assigned managed identities
  • Metadata for tracking and auditing

These omissions are intentional: the goal is to illustrate how each assignment feature is wired, not provide drop-in governance modules. See the PolicyAssignment resource reference for all available configuration options.

Let's configure Azure Policy Assignments

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Enforcement & Compliance
How do I test a policy without enforcing it?
Set enforcementMode to DoNotEnforce to audit compliance without blocking resource operations. This allows you to see which resources would be non-compliant without actually preventing their creation or modification.
How do I enforce a policy only on newly created or updated resources?
Set enforcementMode to Enroll to apply the policy effect only during resource creation or update operations. Existing resources that don’t comply won’t be affected.
How do I provide different non-compliance messages for different policies in a policy set?
Use the policyDefinitionReferenceId field in nonComplianceMessages to target specific policies within the set. Without this field, the message applies to all policies in the assignment.
Identity & Permissions
Why do I need to specify a location for my policy assignment?
Location is required only when using a managed identity with the policy assignment. Set the location property when configuring the identity field.
Scope & Targeting
What properties can't I change after creating a policy assignment?
Three properties are immutable: scope (where the policy is assigned), policyAssignmentName (the assignment name), and assignmentType (NotSpecified, System, SystemHidden, or Custom). You must delete and recreate the assignment to change these.
How do I apply a policy only to specific regions?
Use resourceSelectors with kind: resourceLocation and specify the regions in the in array. This filters which resources the policy applies to based on their location.
What's the difference between overrides and resource selectors?
Resource selectors filter which resources the policy applies to (e.g., only resources in certain regions). Overrides change how the policy behaves for selected resources (e.g., changing the policy effect from Deny to Audit).
Advanced Configuration
Can I override policy effects for specific resources or regions?
Yes, use overrides with selectors to change policy effects or definition versions. For example, you can set kind: policyEffect with value: Audit and use selectors to target specific policy definitions or resource locations.
How do I specify which version of a policy definition to use?
Set the definitionVersion property with a specific version or wildcard pattern (e.g., 1.*.*). You can also use overrides to apply different versions to different regions.
How do I pass parameter values to a policy definition?
Use the parameters property with key-value pairs where keys are parameter names and values are objects containing a value field. For example, parameters: { prefix: { value: "DeptA" } }.
When does the instanceId change?
The instanceId only changes when the policy assignment is deleted and recreated. It remains the same for all updates to an existing assignment.

Using a different cloud?

Explore security guides for other cloud providers: