Managing Custom Azure Roles
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Managing Custom Azure Roles
In the world of cloud security, the concept of "identity" is the new perimeter. Gone are the days when we could rely solely on a firewall to keep the bad actors out. Today, we manage access through identities—users, groups, and service principals. One of the most critical aspects of managing these identities in Azure is Role-Based Access Control (RBAC). While Microsoft provides hundreds of built-in roles like "Owner," "Contributor," and "Reader," these often follow a "one-size-fits-all" approach that might not align with your organization’s specific security requirements.
This is where custom roles come into play. Managing custom Azure roles allows you to adhere to the Principle of Least Privilege (PoLP), ensuring that users have exactly the permissions they need to do their jobs—nothing more and nothing less. If a built-in role is too broad, you risk accidental or malicious configuration changes. If it is too restrictive, you hinder productivity. Custom roles provide the "Goldilocks" solution: the perfect fit for your specific operational needs.
In this lesson, we will dive deep into the architecture of Azure roles, explore how to design and implement custom roles using various tools, and discuss the governance strategies required to maintain a secure environment.
Understanding the Foundation of Azure RBAC
Before we start building custom roles, we need to understand how Azure interprets permissions. Every role in Azure, whether built-in or custom, is essentially a JSON (JavaScript Object Notation) file that defines a set of allowed and disallowed actions. These actions are mapped to Azure Resource Providers, such as Microsoft.Compute for virtual machines or Microsoft.Storage for storage accounts.
An Azure role definition consists of several key components:
- Actions: These are the management-plane operations that the role is allowed to perform (e.g., starting a VM, creating a website).
- NotActions: These are operations excluded from the allowed actions. It is important to note that
NotActionsis not a "Deny" rule; it is a subtraction from the wildcard list in theActionssection. - DataActions: These apply to the data plane. For example, reading the actual blobs inside a storage container or messages in a queue.
- NotDataActions: Similar to
NotActions, but for the data plane. - AssignableScopes: This defines where the role can be used. You can make a role available across an entire Management Group, a specific Subscription, or a single Resource Group.
Callout: Actions vs. DataActions It is vital to distinguish between the management plane and the data plane. Actions control the resource itself (e.g., "Can I delete this SQL Server?"). DataActions control the data within that resource (e.g., "Can I read the rows inside the database tables?"). Many built-in roles only grant management plane access, so if your developers need to upload files to a storage account, you must ensure the role includes the appropriate
DataActions.
The Anatomy of a Role Definition
To manage custom roles effectively, you must become comfortable reading and writing the JSON schema that defines them. Let’s look at a practical example of a custom role designed for a "Virtual Machine Operator" who needs to start and stop VMs but should not be allowed to delete them or change the networking configuration.
{
"Name": "Virtual Machine Operator (Custom)",
"Id": "88888888-8888-8888-8888-888888888888",
"IsCustom": true,
"Description": "Can monitor, start, and restart virtual machines.",
"Actions": [
"Microsoft.Storage/*/read",
"Microsoft.Network/*/read",
"Microsoft.Compute/*/read",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Authorization/*/read",
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Insights/alertRules/*",
"Microsoft.Support/*"
],
"NotActions": [
"Microsoft.Compute/virtualMachines/delete"
],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/c276fc84-5f40-4742-84c9-9432048b67ee"
]
}
Breaking Down the JSON
- Name and Description: These should be clear and descriptive. Avoid vague names like "Custom Role 1." Instead, use names that reflect the job function.
- IsCustom: For custom roles, this must always be set to
true. - Actions: Notice the use of wildcards (
*).Microsoft.Compute/*/readallows the user to see all resources under the Compute provider. However, the specificactionpermissions allow them to actually click the "Start" and "Restart" buttons in the portal. - NotActions: In this example, we explicitly subtracted the
deletepermission. If the user hadMicrosoft.Compute/virtualMachines/*in the Actions list, theNotActionsentry would prevent them from deleting VMs. - AssignableScopes: This is perhaps the most important part of the definition. If you define a role at the subscription level, it can be assigned to any resource within that subscription. If you define it at the Management Group level, it can be used across multiple subscriptions.
Note: You can have up to 5,000 custom roles in a single Azure AD tenant. While this sounds like a lot, it is a best practice to keep the number of custom roles to a minimum to avoid administrative complexity. Always check if a built-in role can be used with a more restrictive scope before creating a new custom role.
When to Create a Custom Role: Real-World Scenarios
It is easy to get carried away and create a custom role for every user request. However, custom roles require maintenance. When Microsoft adds new features to a Resource Provider, built-in roles are often updated automatically. Custom roles are not. You are responsible for updating them.
Here are three scenarios where a custom role is the right choice:
Scenario 1: The "Tier 1 Support" Auditor
Your support team needs to view the configuration of Network Security Groups (NSGs) and Firewall rules to troubleshoot connectivity issues, but your security policy dictates they should not have "Reader" access to the entire subscription because that would allow them to see sensitive metadata in other services.
- Solution: Create a custom role that only includes
readactions forMicrosoft.Network/*.
Scenario 2: The "DevOps Automation" Service Principal
You have a CI/CD pipeline that needs to deploy Web Apps but should not be allowed to touch SQL Databases or Key Vaults. The built-in "Contributor" role is far too powerful as it allows full control over almost everything.
- Solution: Create a custom role that includes
Microsoft.Web/*andMicrosoft.Insights/*permissions only.
Scenario 3: The "Log Analyst"
A third-party auditor needs to view Activity Logs and Resource Logs but should not be able to see the actual resources or their configurations.
- Solution: Create a custom role with permissions for
Microsoft.Insights/logs/*andMicrosoft.Insights/eventtypes/*.
Step-by-Step: Creating a Custom Role via the Azure Portal
The Azure Portal provides a user-friendly wizard for creating custom roles. This is often the best place to start because it allows you to clone an existing role.
- Navigate to Subscriptions: Open the Azure Portal, search for "Subscriptions," and select the subscription where you want the role to be available.
- Access Control (IAM): Click on the "Access control (IAM)" blade on the left-hand menu.
- Add Custom Role: Click the "+ Add" button and select "Add custom role."
- Basics Tab:
- Provide a unique name.
- Choose "Clone a role" if you want to start with a template (e.g., clone "Reader" and add specific write permissions) or "Start from scratch."
- Permissions Tab: Click "Add permissions." Search for the Resource Provider (e.g.,
Microsoft.Storage). Select the specific permissions you want to add. - Assignable Scopes Tab: By default, the current subscription is added. You can add more subscriptions or management groups here.
- JSON Tab: Review the generated JSON. This is a great way to learn the syntax. You can also download this JSON for use in automation scripts later.
- Review + Create: Click "Create" to finalize the role.
Step-by-Step: Creating a Custom Role via PowerShell
For those who manage multiple environments, PowerShell is the preferred method. It allows for version control and repeatable deployments.
1. Export an existing role to use as a template
# Get the definition of the Reader role
$role = Get-AzRoleDefinition -Name "Reader"
# Convert it to a custom object and clear the ID and IsCustom flag for the new role
$role.Id = $null
$role.Name = "Custom Storage Auditor"
$role.Description = "Can only read storage account configurations and logs."
$role.IsCustom = $true
$role.Actions.Clear()
$role.Actions.Add("Microsoft.Storage/storageAccounts/read")
$role.Actions.Add("Microsoft.Insights/logs/read")
# Define the scope (Replace with your Subscription ID)
$role.AssignableScopes.Clear()
$role.AssignableScopes.Add("/subscriptions/00000000-0000-0000-0000-000000000000")
2. Create the new role
# Create the role in Azure
New-AzRoleDefinition -Role $role
Tip: When using PowerShell, always verify the role after creation using
Get-AzRoleDefinition -Name "Your Role Name". This ensures that theAssignableScopesandActionswere processed correctly.
Comparison of Role Management Tools
| Feature | Azure Portal | Azure CLI / PowerShell | Bicep / ARM Templates |
|---|---|---|---|
| Ease of Use | High (Visual) | Medium (Scripting) | Low (Coding) |
| Repeatability | Low | High | Very High |
| Version Control | No | Yes (via scripts) | Yes (Infrastructure as Code) |
| Bulk Operations | No | Yes | Yes |
| Best For | One-off roles | Admin tasks/Automation | Production environments |
Managing the Lifecycle of Custom Roles
Creating a role is only the first step. Over time, you will need to update permissions, expand scopes, or retire roles that are no longer needed.
Updating a Custom Role
When you update a custom role, the changes propagate to all users and groups assigned to that role. This is powerful but dangerous. If you accidentally remove a permission, you could break production workflows instantly.
To update a role via CLI:
- Download the current definition to a JSON file:
az role definition list --name "My Custom Role" > role-def.json - Modify the
role-def.jsonfile in a text editor. - Update the role:
az role definition update --role-definition role-def.json
Deleting a Custom Role
Before deleting a role, you must ensure there are no active assignments. Azure will allow you to delete a role even if it is assigned to users, but those users will immediately lose access, and their "Role Assignment" entries will show an "Identity Not Found" or "Unknown" status.
Warning: Deleting a role is permanent. There is no "Recycle Bin" for RBAC roles. Always keep a backup of your role definition JSON files in a Git repository.
Best Practices for Custom Role Management
1. Follow the Principle of Least Privilege
The primary reason for custom roles is to limit access. Do not use wildcards (*) unless absolutely necessary. For example, instead of Microsoft.Compute/*, use Microsoft.Compute/virtualMachines/read. This prevents the user from having access to other compute resources like Disk Encryption Sets or Proximity Placement Groups.
2. Use Descriptive and Consistent Naming
In a large organization, it’s easy to lose track of what a role does. Use a naming convention such as:
[Department] - [Resource Type] - [Access Level]
Example: Finance - Storage - Auditor
3. Minimize the Use of NotActions
NotActions can be confusing. Remember that NotActions only subtracts from the Actions list in the same role definition. If a user is assigned two roles—one that grants "Contributor" and another that is a custom role with Microsoft.Compute/virtualMachines/delete in the NotActions list—the user can still delete virtual machines. This is because the "Contributor" role grants the permission, and Azure RBAC is additive.
Callout: NotActions is NOT a Deny A common mistake is thinking
NotActionsworks like a Deny rule in a firewall. It does not. If any role assigned to a user grants a permission, the user has that permission. To truly deny an action regardless of other roles, you would need to use Azure Resource Locks or Azure Policy, or in specific cases, Deny Assignments (which are currently primarily used by Azure Blueprints and Managed Applications).
4. Limit AssignableScopes
Avoid setting the AssignableScopes to the Root Management Group (/) unless the role is truly universal. By limiting the scope to specific subscriptions or management groups, you reduce the "blast radius" of the role and keep the role list clean for administrators in other parts of the organization.
5. Regularly Audit Role Usage
Use Azure AD Access Reviews to check if users still need the custom roles they have been assigned. Additionally, use the "Activity Log" to see who has modified custom role definitions. This provides an audit trail for compliance.
Common Pitfalls and How to Avoid Them
Pitfall 1: Forgetting DataActions
As mentioned earlier, many people create a role to manage Storage Accounts or Key Vaults but forget to include DataActions. The user ends up being able to see the Storage Account in the portal but gets an "Access Denied" error when trying to view the files.
- Fix: Always check the Resource Provider documentation to see if the task requires Data Plane permissions.
Pitfall 2: Overlapping Scopes
If you define a custom role at a Subscription level and then define an identical one at a Resource Group level, you create confusion.
- Fix: Define roles at the highest common level (usually a Management Group or Subscription) and then use "Role Assignments" to narrow down who gets that access at the lower levels.
Pitfall 3: Hardcoding Subscription IDs in JSON
When sharing role definitions across different environments (Dev, Test, Prod), hardcoding the subscription ID in the AssignableScopes will cause the deployment to fail in the new environment.
- Fix: Use placeholders or variables in your scripts to dynamically insert the correct Subscription ID during the deployment process.
Pitfall 4: Reaching the Assignment Limit
While you can have 5,000 role definitions, there is also a limit on role assignments (around 2,000 per subscription). If you create too many granular roles and assign them to individual users rather than groups, you will hit this limit quickly.
- Fix: Always assign roles to Groups, not individual users.
Advanced Concept: Using Bicep for Custom Roles
As organizations move toward Infrastructure as Code (IaC), managing roles through the portal becomes a liability. Bicep is Microsoft's domain-specific language for deploying Azure resources. Using Bicep to manage roles ensures that your security configuration is documented and versioned.
Here is what a custom role looks like in Bicep:
targetScope = 'subscription'
resource customRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
name: guid('NetworkAuditorRole')
properties: {
roleName: 'Network Auditor (Bicep)'
description: 'Custom role for auditing network settings.'
type: 'CustomRole'
permissions: [
{
actions: [
'Microsoft.Network/*/read'
'Microsoft.Insights/diagnosticSettings/read'
]
notActions: []
}
]
assignableScopes: [
subscription().id
]
}
}
Using the guid() function for the name is a best practice because role names in the back-end must be unique GUIDs. This ensures that every time you deploy this Bicep file, it correctly identifies the existing role rather than trying to create a duplicate.
Quick Reference: Built-in vs. Custom Roles
| Feature | Built-in Roles | Custom Roles |
|---|---|---|
| Creation | Managed by Microsoft | Managed by you |
| Updates | Automatic when services change | Manual update required |
| Flexibility | Fixed permissions | Fully customizable |
| Scope | Available tenant-wide | Limited to AssignableScopes |
| Maintenance | Zero overhead | Requires regular review |
Troubleshooting Custom Roles
If a user reports that they cannot perform an action despite being assigned a custom role, follow this troubleshooting workflow:
- Check the Scope: Is the user trying to perform the action on a resource that falls within the
AssignableScopesof the role? - Verify the Action: Look at the "JSON View" of the resource in the portal. Find the
typeand the operation being performed. Does it match an entry in theActionslist of your custom role? - Check for Other Roles: Does the user have another role assigned (perhaps at a higher scope like the Management Group) that includes a
NotActionsor a different set of permissions? - Wait for Propagation: Role assignments and definition changes can take up to 5-10 minutes to propagate across all Azure regions.
- Use the "Check Access" Tool: In the "Access control (IAM)" blade, use the "Check access" tab to see a definitive list of permissions a specific user has on that specific resource. This tool is invaluable for debugging complex RBAC scenarios.
Summary and Key Takeaways
Managing custom Azure roles is a balancing act between security and usability. By moving away from overly broad built-in roles and toward tailored custom roles, you significantly improve your organization's security posture. However, this comes with the responsibility of maintaining those roles as Azure evolves.
Key Takeaways:
- Principle of Least Privilege: Custom roles are the primary tool for ensuring users have only the permissions required for their specific job functions.
- JSON Structure: Understanding the
Actions,NotActions, andDataActionsfields is essential for creating effective roles. - AssignableScopes Matter: Carefully define where a role can be used to prevent "role bloat" and maintain a clean administrative environment.
- Additive Nature: Azure RBAC is additive. A
NotActionin one role will not override anActiongranted in another role. - Prefer Groups: Always assign custom roles to Azure AD Groups rather than individuals to stay under assignment limits and simplify management.
- Automation is King: Use PowerShell, CLI, or Bicep to manage roles in production. This allows for versioning and ensures consistency across environments.
- Regular Audits: Treat custom roles as living documents. Review them periodically to ensure they still meet security requirements and don't contain obsolete permissions.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons