Manage Azure Role Assignments

The azure-native:authorization:RoleAssignment resource, part of the Pulumi Azure Native provider, links Azure AD principals to role definitions at a specific scope: subscription, resource group, or individual resource. This guide focuses on two capabilities: scope hierarchy and principal-to-role linking.

Role assignments connect existing Azure AD principals to existing role definitions. The target scope must already exist. The examples are intentionally small. Combine them with your own principal IDs, role definitions, and resource paths.

Grant subscription-wide access to a user

Most deployments begin by granting access at the subscription level, allowing principals to manage resources across all resource groups.

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

const roleAssignment = new azure_native.authorization.RoleAssignment("roleAssignment", {
    principalId: "ce2ce14e-85d7-4629-bdbc-454d0519d987",
    principalType: azure_native.authorization.PrincipalType.User,
    roleAssignmentName: "05c5a614-a7d6-4502-b150-c2fb455033ff",
    roleDefinitionId: "/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
    scope: "subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2",
});
import pulumi
import pulumi_azure_native as azure_native

role_assignment = azure_native.authorization.RoleAssignment("roleAssignment",
    principal_id="ce2ce14e-85d7-4629-bdbc-454d0519d987",
    principal_type=azure_native.authorization.PrincipalType.USER,
    role_assignment_name="05c5a614-a7d6-4502-b150-c2fb455033ff",
    role_definition_id="/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
    scope="subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2")
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.NewRoleAssignment(ctx, "roleAssignment", &authorization.RoleAssignmentArgs{
			PrincipalId:        pulumi.String("ce2ce14e-85d7-4629-bdbc-454d0519d987"),
			PrincipalType:      pulumi.String(authorization.PrincipalTypeUser),
			RoleAssignmentName: pulumi.String("05c5a614-a7d6-4502-b150-c2fb455033ff"),
			RoleDefinitionId:   pulumi.String("/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d"),
			Scope:              pulumi.String("subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2"),
		})
		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 roleAssignment = new AzureNative.Authorization.RoleAssignment("roleAssignment", new()
    {
        PrincipalId = "ce2ce14e-85d7-4629-bdbc-454d0519d987",
        PrincipalType = AzureNative.Authorization.PrincipalType.User,
        RoleAssignmentName = "05c5a614-a7d6-4502-b150-c2fb455033ff",
        RoleDefinitionId = "/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
        Scope = "subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.RoleAssignment;
import com.pulumi.azurenative.authorization.RoleAssignmentArgs;
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 roleAssignment = new RoleAssignment("roleAssignment", RoleAssignmentArgs.builder()
            .principalId("ce2ce14e-85d7-4629-bdbc-454d0519d987")
            .principalType("User")
            .roleAssignmentName("05c5a614-a7d6-4502-b150-c2fb455033ff")
            .roleDefinitionId("/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d")
            .scope("subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2")
            .build());

    }
}
resources:
  roleAssignment:
    type: azure-native:authorization:RoleAssignment
    properties:
      principalId: ce2ce14e-85d7-4629-bdbc-454d0519d987
      principalType: User
      roleAssignmentName: 05c5a614-a7d6-4502-b150-c2fb455033ff
      roleDefinitionId: /subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d
      scope: subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2

The scope property defines where permissions apply. A subscription scope grants access to all resources within that subscription. The principalId identifies the Azure AD user, service principal, or managed identity receiving permissions. The roleDefinitionId specifies which built-in or custom role to assign. The principalType clarifies whether the principal is a User, ServicePrincipal, or other type.

Scope access to a resource group

Teams often isolate environments into resource groups and grant access only within that boundary.

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

const roleAssignment = new azure_native.authorization.RoleAssignment("roleAssignment", {
    principalId: "ce2ce14e-85d7-4629-bdbc-454d0519d987",
    principalType: azure_native.authorization.PrincipalType.User,
    roleAssignmentName: "05c5a614-a7d6-4502-b150-c2fb455033ff",
    roleDefinitionId: "/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
    scope: "subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg",
});
import pulumi
import pulumi_azure_native as azure_native

role_assignment = azure_native.authorization.RoleAssignment("roleAssignment",
    principal_id="ce2ce14e-85d7-4629-bdbc-454d0519d987",
    principal_type=azure_native.authorization.PrincipalType.USER,
    role_assignment_name="05c5a614-a7d6-4502-b150-c2fb455033ff",
    role_definition_id="/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
    scope="subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg")
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.NewRoleAssignment(ctx, "roleAssignment", &authorization.RoleAssignmentArgs{
			PrincipalId:        pulumi.String("ce2ce14e-85d7-4629-bdbc-454d0519d987"),
			PrincipalType:      pulumi.String(authorization.PrincipalTypeUser),
			RoleAssignmentName: pulumi.String("05c5a614-a7d6-4502-b150-c2fb455033ff"),
			RoleDefinitionId:   pulumi.String("/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d"),
			Scope:              pulumi.String("subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg"),
		})
		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 roleAssignment = new AzureNative.Authorization.RoleAssignment("roleAssignment", new()
    {
        PrincipalId = "ce2ce14e-85d7-4629-bdbc-454d0519d987",
        PrincipalType = AzureNative.Authorization.PrincipalType.User,
        RoleAssignmentName = "05c5a614-a7d6-4502-b150-c2fb455033ff",
        RoleDefinitionId = "/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
        Scope = "subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.RoleAssignment;
import com.pulumi.azurenative.authorization.RoleAssignmentArgs;
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 roleAssignment = new RoleAssignment("roleAssignment", RoleAssignmentArgs.builder()
            .principalId("ce2ce14e-85d7-4629-bdbc-454d0519d987")
            .principalType("User")
            .roleAssignmentName("05c5a614-a7d6-4502-b150-c2fb455033ff")
            .roleDefinitionId("/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d")
            .scope("subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg")
            .build());

    }
}
resources:
  roleAssignment:
    type: azure-native:authorization:RoleAssignment
    properties:
      principalId: ce2ce14e-85d7-4629-bdbc-454d0519d987
      principalType: User
      roleAssignmentName: 05c5a614-a7d6-4502-b150-c2fb455033ff
      roleDefinitionId: /subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d
      scope: subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg

The scope narrows to a resource group path, limiting permissions to resources within that group. This follows Azure’s hierarchical permission model: assignments at narrower scopes override broader ones. The same principal and role definition properties apply, but the scope path now includes the resource group name.

Grant access to a specific resource

For fine-grained control, you can assign permissions to individual resources like storage accounts or databases.

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

const roleAssignment = new azure_native.authorization.RoleAssignment("roleAssignment", {
    principalId: "ce2ce14e-85d7-4629-bdbc-454d0519d987",
    principalType: azure_native.authorization.PrincipalType.User,
    roleAssignmentName: "05c5a614-a7d6-4502-b150-c2fb455033ff",
    roleDefinitionId: "/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
    scope: "subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg/providers/Microsoft.DocumentDb/databaseAccounts/test-db-account",
});
import pulumi
import pulumi_azure_native as azure_native

role_assignment = azure_native.authorization.RoleAssignment("roleAssignment",
    principal_id="ce2ce14e-85d7-4629-bdbc-454d0519d987",
    principal_type=azure_native.authorization.PrincipalType.USER,
    role_assignment_name="05c5a614-a7d6-4502-b150-c2fb455033ff",
    role_definition_id="/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
    scope="subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg/providers/Microsoft.DocumentDb/databaseAccounts/test-db-account")
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.NewRoleAssignment(ctx, "roleAssignment", &authorization.RoleAssignmentArgs{
			PrincipalId:        pulumi.String("ce2ce14e-85d7-4629-bdbc-454d0519d987"),
			PrincipalType:      pulumi.String(authorization.PrincipalTypeUser),
			RoleAssignmentName: pulumi.String("05c5a614-a7d6-4502-b150-c2fb455033ff"),
			RoleDefinitionId:   pulumi.String("/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d"),
			Scope:              pulumi.String("subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg/providers/Microsoft.DocumentDb/databaseAccounts/test-db-account"),
		})
		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 roleAssignment = new AzureNative.Authorization.RoleAssignment("roleAssignment", new()
    {
        PrincipalId = "ce2ce14e-85d7-4629-bdbc-454d0519d987",
        PrincipalType = AzureNative.Authorization.PrincipalType.User,
        RoleAssignmentName = "05c5a614-a7d6-4502-b150-c2fb455033ff",
        RoleDefinitionId = "/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d",
        Scope = "subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg/providers/Microsoft.DocumentDb/databaseAccounts/test-db-account",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.authorization.RoleAssignment;
import com.pulumi.azurenative.authorization.RoleAssignmentArgs;
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 roleAssignment = new RoleAssignment("roleAssignment", RoleAssignmentArgs.builder()
            .principalId("ce2ce14e-85d7-4629-bdbc-454d0519d987")
            .principalType("User")
            .roleAssignmentName("05c5a614-a7d6-4502-b150-c2fb455033ff")
            .roleDefinitionId("/subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d")
            .scope("subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg/providers/Microsoft.DocumentDb/databaseAccounts/test-db-account")
            .build());

    }
}
resources:
  roleAssignment:
    type: azure-native:authorization:RoleAssignment
    properties:
      principalId: ce2ce14e-85d7-4629-bdbc-454d0519d987
      principalType: User
      roleAssignmentName: 05c5a614-a7d6-4502-b150-c2fb455033ff
      roleDefinitionId: /subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/providers/Microsoft.Authorization/roleDefinitions/0b5fe924-9a61-425c-96af-cfe6e287ca2d
      scope: subscriptions/a925f2f7-5c63-4b7b-8799-25a5f97bc3b2/resourceGroups/testrg/providers/Microsoft.DocumentDb/databaseAccounts/test-db-account

The scope path extends to a specific resource, providing the narrowest possible permissions. This example targets a Cosmos DB account, but the pattern applies to any Azure resource. The scope format follows Azure’s resource ID structure: subscription, resource group, provider namespace, and resource name.

Beyond these examples

These snippets focus on specific role assignment features: scope hierarchy (subscription, resource group, resource) and principal and role definition linking. They’re intentionally minimal rather than full access control solutions.

The examples reference pre-existing infrastructure such as Azure AD principals (users, service principals, managed identities), role definitions (built-in or custom), and target resources, resource groups, or subscriptions. They focus on configuring the assignment rather than creating the underlying identity or authorization infrastructure.

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

  • Conditional access policies (condition, conditionVersion)
  • Delegated managed identity assignments
  • Assignment descriptions and metadata
  • Time-based or attribute-based access control

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

Let's manage Azure Role Assignments

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Scope & Configuration
How do I assign a role at different scope levels?

Use the scope property with different formats depending on the target level:

  • Subscription: /subscriptions/{subscriptionId}
  • Resource group: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}
  • Specific resource: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}
What format should I use for roleDefinitionId?
Use the full Azure Resource Manager path: /subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/{roleDefinitionId}. The role definition ID is a GUID representing the built-in or custom role.
Immutability & Lifecycle
What properties can't I change after creating a role assignment?
Three properties are immutable and require resource replacement if changed: principalId, scope, and roleAssignmentName.
Resource Naming
How do I generate the roleAssignmentName?
The roleAssignmentName can be any valid GUID. You can generate one using your programming language’s UUID/GUID library or let Pulumi auto-name the resource.
Advanced Features
How do I restrict a role assignment to specific resources using conditions?
Use the condition property with an expression like @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase 'foo_storage_container'. Set conditionVersion to 2.0 (currently the only accepted value).

Using a different cloud?

Explore security guides for other cloud providers: