Resource locks provide a way to lock down your Azure resources to prevent deletion or modification of sensitive artifacts. You can read more about it in my blog Avoid accidental removal of Azure resources. The Azure DevOps identity – that is used to deploy your Azure solutions – is often a Contributor within a subscription, so it has all the necessary rights to perform the required releases.
However, as a Contributor you cannot create or delete such resource locks. That’s why Azure DevOps is often granted role Owner role. This is a quick workaround, but introduces a significant security risk. People can abuse the Azure DevOps Owner role to grant access to whomever they want. This blog discusses a more secure alternative.
Create a contributor with resource lock rights
In order to create or delete resource locks, you must have access to the to Microsoft.Authorization/* or Microsoft.Authorization/locks/* actions. Within the built-in roles, only Owner and User Access Administrator are granted those actions. As stated before, I would like to avoid this. What I actually want, is to create a custom role that is identical to the Contributor role, but has additional access to deploy resource locks. After some investigation, I found out that the following role definition is what I need:
{ "Id": null, "Name": "Contributor with resource lock rights", "IsCustom": true, "Description": "Equivalent of contributor role, with additional right to deploy resource locks", "Actions": [ "*" ], "NotActions": [ "Microsoft.Authorization/locks/delete", "Microsoft.Authorization/classicAdministrators/*", "Microsoft.Authorization/denyAssignments/*", "Microsoft.Authorization/elevateAccess/*", "Microsoft.Authorization/operations/*", "Microsoft.Authorization/permissions/*", "Microsoft.Authorization/policyAssignments/*", "Microsoft.Authorization/policyDefinitions/*", "Microsoft.Authorization/policySetDefinitions/*", "Microsoft.Authorization/providerOperations/*", "Microsoft.Authorization/roleAssignments/*", "Microsoft.Authorization/roleDefinitions/*", "Microsoft.Authorization/elevateAccess/Action", "Microsoft.Blueprint/blueprintAssignments/write", "Microsoft.Blueprint/blueprintAssignments/delete" ], "DataActions": [ ], "NotDataActions": [ ], "AssignableScopes": [ "/subscriptions/********-****-****-****-************" ] }
This role definition can be easily deployed with Azure PowerShell:
Set-AzRoleDefinition -InputFile ".\roleDefinition.json"
Now, the custom role can be used in Azure:
Configure Azure DevOps with this role
Now, we have to configure Azure DevOps to use this role.
- The first step is creating a service principal.
- Secondly, you need to grant this principal Contributor with resource locks rights on the subscription
- Finally, use this service principal to create a service connection in Azure DevOps
What if DevOps needs User Access Admin rights?
In some cases, Azure DevOps really requires elevated permissions. If you encounter this, you can create a DevOps service connection that has for example User Access Admin rights. However, you don’t want that everyone in the organization can use this connection. That’s why Azure DevOps has foreseen security controls on a service connection. Be careful when assigning the following roles:
- User: members of this role can use the service connection when authoring build or release pipelines.
- Administrator: in addition to using the service connection, members of this role can manage membership of all other roles for the service connection. The user that created the service connection is automatically added to the Administrator role for that service connection.
Conclusion
Azure and Azure DevOps have the required tools to tailor security to your needs. Always apply the principle of least privilege, when granting access to users and processes.
And remember: sharing is caring!
Thanks,
Toon