RBAC cleanup: putting developers on a PIM diet

When you can not see the wood for the trees, it's time to cut some role assignments.

Note: This post is part of the Azure Spring Clean 2024. Make sure to have a look at the list of other topics provided by the community.

When a company looks at cleaning up user (admin) access, or even ’locking down’ access with tools like PIM, it is typically done for Microsoft Entra ID roles. The reasoning behind this is partially correct: a Microsoft Entra ID administrator role (and certainly Global Administrator) can do quite some tasks and thus ‘do a lot of wrong things’ which makes it a risk. That’s why we try to limit access following the least-privilege-principle.

Note: You can find a list of all Microsoft Entra ID built-in roles and even guidance on least-privilege roles for specific tasks in Microsoft Entra ID on the Azure docs. When in doubt, look it up rather than going the easy path and give a broad role like Global Administrator.

However, what typically is forgotten in an organization, is the access that developers have. Microsoft Entra ID roles are usually well managed, but Azure RBAC roles often grow rampant. After all, I have heard plenty of developers say ‘I need access to be able to do my job’.

For any organization making significant use of Azure resources, the risk might be as big as with Microsoft Entra ID. It can range from compromised accounts, over malicious actions by displeased employees or even simple human error. The impact?

  • Data leaks due to an undesired access to Azure SQL, storage accounts, …
  • Unexpected costs due to crypto-mining VMs.
  • Misconfigured resources due to lack of knowledge or human error, often resulting in extra costs or data leaks by itself, or simply a broken system.
  • Resources being deleted by accident (or even worse, intentional).

Azure resources RBAC?

In short, Azure RBAC is an authorization system built on Azure Resource Manager that provides fine-grained access management to Azure resources.

This is done by giving a certain user or application (1: called security principal) specific access (2: role definition) to a certain resource or collection of resources (3: scope).

Azure Resources RBAC

Here we try to follow least-privilege as well, which is typically done by finding resource specific roles like e.g. Key Vault Secrets User for an application that needs access to secrets. Initially, it will feel like a lot of extra work, but in the long run security always pays off.

Note: Similar to Microsoft Entra ID, there is also a huge list of Azure resources built-in roles. Each role also comes with an id, which makes automating through IaC a bit easier.

Note: There is an important difference between control plane and data plane RBAC roles. The first is for managing the actual Azure resources, while the latter gives access to data in these resources. Example: An Owner can do all management actions (create, assign RBAC, …) on an Azure Key Vault, but can’t read secrets without assigning a role like Key Vault Secrets User.

The ideal world

As with Microsoft Entra ID, Azure resources have best practices for RBAC. The picture below gives a high-level overview of what you can expect to set up, with least-privilege going from left to right. As you can see, resource-specific roles are more limiting than Contributor or Owner roles and should be used when possible (and manageable).

Azure resources RBAC suggested pattern

Custom roles might be a solution to minimize the number of resource-specific roles to be assigned in your solution, but be sure to test these thoroughly before using in production. If you want to use this approach, certainly have a look at the roles provided by the Azure landing zone accelerator.

Assigning roles should typically be done by using Microsoft Entra ID security groups. First of all, a group with a good name shows intent of what that group should be able to do, making reviews easier. Second, configuring Azure RBAC security once and afterwards adding persons to a ‘RBAC role security group’ is a lot easier to do correctly than trying to repeat the configuration for every new person on the team.

The reality

Most customers I’ve assisted over the years forget to use security groups, and almost all of them ignore the resource-specific roles.

Looking at one of the resource groups owned by a team of +- 10 devs, we can immediately see the results of the lack of security governance.

Azure RBAC overload

Without showing the details, you can already propose a few improvements:

  • Use security groups instead of assigning to 40 individuals.
  • Start trimming down on privileged roles: with such a small team, do we need 24 identities being able to do ’everything except assigning roles’ and another 27 identities able to do the ’everything’ and assign security?

Note: Even with a security group for the developers, you’ll end up with a handful of Owner/Contributor assignments: Azure admins (trickling down from the management groups, including foreign principals for CSP), a deployment pipeline (service principal) for your IaC/RBAC assignments and maybe the devs through PIM.

Let’s go all the way

I’ve mentioned least-privilege-principle before and in my session on ‘Developer productivity shouldn’t breach security’ I present following table as my opinion of the security required for a developer team (at some customers I set it up to be even more strict):

Scope Development Test Staging Production
Subscription Reader (*) Reader Reader Reader
Resource group Contributor (*) Reader Reader Reader
Storage Account Storage Blob Data Contributor Storage Blob Data Contributor (*) Storage Blob Data Reader N/A
SQL Fix with SQL roles SQL roles SQL roles N/A

In my opinion: devs should NOT have write access to production (Azure) resources or read access to production data (by default). This will prevent from accidental misconfiguration, deletion, data tampering, data leaks, …

  • Any corrective data actions in production should be done through the application or tested tools.
  • Production databases with PII should never be restored to lower environments without cleansing.

But I need to be able to do my job!

The typical excuse from developers when they want more security. “I can’t support the application if I don’t have access to production!

I have been on both sides, so I know this does work. It does require a mind shift though, where both DevOps and testing become very important.

  • All changes in any environment above Development are fully automated.
    I typically go one step further and include Development as well. In this case, devs can use a Research environment with contributor rights.
  • This also means data seeding, imports, corrections, … which can be automated. Exceptional cases should be able to be fixed through your application or specific admin tool.

Note: Any paid Visual Studio subscription comes with free Azure credits. Enable those credits and you have extra research environments to try out (smaller) things.

PIM for developers

If for some very specific reason your developers (or support team) still need access to production resources, then make sure to limit it in time by using PIM. Since it’s so important, I’ll repeat some of the key features:

  • Provide just-in-time privileged access to Microsoft Entra ID and Azure resources
  • Assign time-bound access to resources using start and end dates
  • Require approval to activate privileged roles
  • Enforce multifactor authentication to activate any role
  • Use justification to understand why users activate
  • Get notifications when privileged roles are activated
  • Conduct access reviews to ensure users still need roles
  • Download audit history for internal or external audit

Assign PIM

You can find PIM for Azure resources under Microsoft Entra ID in the portal (or the Microsoft Entra Admin Center) > Privileged Identity Management > Azure Resources.

Find the correct scope to which you want to assign occasional elevated access (through PIM). In the screenshot below, I assign it on resource group. The steps following are similar to Microsoft Entra ID PIM to assign security principals as eligible or active. Since we want just-in-time access, we opt for eligible.

Azure RBAC overload

More info on the official docs (which currently has old images).

Activate PIM

You can go the same path through Microsoft Entra ID > PIM > My roles to activate your eligible roles. However, for Azure resources it can be even easier by just going to the actual resource > Access control (IAM) > View my access. There you can see your eligible roles on the resource and activate them.

Azure RBAC overload

Note: While this step is easier to remember for developers than digging into Microsoft Entra ID, it will require them to have the Reader role to be able to see the resource in the first place.


Security is important, but we often neglect it. After a while, you lose control of your RBAC assignments, resulting in inconsistencies and potential security holes.

Start using security groups for Azure resources RBAC, use resource-specific roles where possible and make use of PIM for occasional elevated access.

Licensed under CC BY-NC-SA 4.0; code samples licensed under MIT.
comments powered by Disqus
Built with Hugo - Based on Theme Stack designed by Jimmy