Azure provides a set of built-in roles with predefined permissions for common job functions. These roles, like Contributor or Reader, are convenient but may grant more access than a user needs. To enforce least-privilege access, you create custom roles. A custom role is a collection of specific permissions you define yourself, allowing you to grant precise access to Azure resources and Microsoft Entra ID that matches your exact organizational requirements when a built-in role is too broad or too narrow.
You define a custom role by creating a JSON document that specifies its properties. The two most critical properties are permissions and assignableScopes. The permissions block defines what actions are allowed or denied. It uses categories like Actions (what you can do to control-plane resources, like create a VM) and DataActions (what you can do to data within a resource, like read a blob). You can also use NotActions and NotDataActions to exclude specific permissions from a broader set. The assignableScopes property lists where this role can be assigned, such as a specific subscription, resource group, or the entire directory for Microsoft Entra roles.
You can create this JSON definition using Azure CLI, Azure PowerShell, or the REST API. Common methods include cloning an existing role's JSON and modifying it, or starting from a blank template. The process involves carefully selecting only the permissions necessary for a task. For example, a role for a backup operator might only need read and backup actions on virtual machines, not delete or write. After authoring, you submit the JSON to Azure to create the role definition in your tenant.
Once a custom role is defined, you assign it to a user, group, or service principal. The scope of this assignment is crucial for security. You can assign the role at the management group, subscription, resource group, or individual resource level in Azure. For Microsoft Entra roles, the scope is typically the entire directory. Assigning a role at the broadest necessary scope follows least-privilege; a user who only needs to manage storage accounts in one resource group should not have that role assigned at the subscription level, as it would unintentionally grant them access to all storage accounts in the subscription.
The Azure authorization system evaluates permissions hierarchically. An assignment at a parent scope (like a subscription) grants those permissions to all child resources (like resource groups and VMs within it). Therefore, you must carefully choose the narrowest assignableScopes when defining the role and the narrowest scope when making the assignment. This layered control ensures that permissions are contained and do not inadvertently spread, maintaining a secure boundary between different parts of your environment.
A top-down hierarchy showing how Azure RBAC scopes flow from Microsoft Entra tenant through management group, subscription, resource group, and individual resource, with permissions inherited by all child scopes.
Are you a guardian of your domain? Lean how to leverage your aptitude in security to protect Microsoft Azure technologies, with a goal of earning the Microsoft Certified: Azure Security Engineer Associate certification!
Prepare and test your skills

Prepare and test your skills

Built-in roles are predefined sets of permissions for common job functions, like Contributor or Reader, while custom roles are collections of specific permissions you define yourself to enforce least-privilege access when a built-in role is too broad or too narrow.
The two most critical properties are the permissions block, which defines allowed or denied actions and data actions, and the assignableScopes property, which lists where the role can be assigned, such as a specific subscription, resource group, or the entire directory for Microsoft Entra roles.
The scope is crucial because assigning a role at a broader scope than necessary, like a subscription instead of a resource group, would unintentionally grant permissions to all child resources, violating the principle of least-privilege access and potentially creating insecure boundaries.