Managing Custom Azure Roles

Earn 25 points (50 with Pro) in two steps

  1. ① Read through the lesson — each section gets a ✓ as you scroll through it.
  2. ② When every section has a ✓, tap Complete lesson.

0 of 12 read · keep scrolling

✦ See fewer ads and earn double points — 50 a lesson instead of 25 — 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.

Not read yet

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:

  1. Actions: These are the management-plane operations that the role is allowed to perform (e.g., starting a VM, creating a website).
  2. NotActions: These are operations excluded from the allowed actions. It is important to note that NotActions is not a "Deny" rule; it is a subtraction from the wildcard list in the Actions section.
  3. DataActions: These apply to the data plane. For example, reading the actual blobs inside a storage container or messages in a queue.
  4. NotDataActions: Similar to NotActions, but for the data plane.
  5. 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.

Not read yet

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/*/read allows the user to see all resources under the Compute provider. However, the specific action permissions allow them to actually click the "Start" and "Restart" buttons in the portal.
  • NotActions: In this example, we explicitly subtracted the delete permission. If the user had Microsoft.Compute/virtualMachines/* in the Actions list, the NotActions entry 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.

Not read yet

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 read actions for Microsoft.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/* and Microsoft.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/* and Microsoft.Insights/eventtypes/*.

Not read yet

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.

  1. Navigate to Subscriptions: Open the Azure Portal, search for "Subscriptions," and select the subscription where you want the role to be available.
  2. Access Control (IAM): Click on the "Access control (IAM)" blade on the left-hand menu.
  3. Add Custom Role: Click the "+ Add" button and select "Add custom role."
  4. 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."
  5. Permissions Tab: Click "Add permissions." Search for the Resource Provider (e.g., Microsoft.Storage). Select the specific permissions you want to add.
  6. Assignable Scopes Tab: By default, the current subscription is added. You can add more subscriptions or management groups here.
  7. 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.
  8. Review + Create: Click "Create" to finalize the role.

Not read yet

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 the AssignableScopes and Actions were processed correctly.

Not read yet

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:

  1. Download the current definition to a JSON file: az role definition list --name "My Custom Role" > role-def.json
  2. Modify the role-def.json file in a text editor.
  3. 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.

Not read yet

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 NotActions works 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.

Not read yet

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.

Not read yet

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.

Not read yet

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:

  1. Check the Scope: Is the user trying to perform the action on a resource that falls within the AssignableScopes of the role?
  2. Verify the Action: Look at the "JSON View" of the resource in the portal. Find the type and the operation being performed. Does it match an entry in the Actions list of your custom role?
  3. Check for Other Roles: Does the user have another role assigned (perhaps at a higher scope like the Management Group) that includes a NotActions or a different set of permissions?
  4. Wait for Propagation: Role assignments and definition changes can take up to 5-10 minutes to propagate across all Azure regions.
  5. 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.

Not read yet

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, and DataActions fields 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 NotAction in one role will not override an Action granted 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.

Not read yet

Each section gets a ✓ as you scroll through it. Tap the button to jump to the next one.