Introduction
Azure supports Role-Based-Access-Control (RBAC) to controll what actions a principal (user, service principal etc) can perform via the Azure Portal, XPlat Cli or Azure PowerShell module.
Azure provides quite a few built-in roles (48 at this time) but it is also possible to define your own custom roles. In this post I will provide a few general tips on RBAC and also how to go about creating your own custom roles.
Actions and NotActions
Actions are permissions/operations that you wish to allow and NotActions are ones that you wish to restrict. When assigning roles you need to be conscious of the fact that NotActions are not deny rules as mentioned in the Microsoft document:
If a user is assigned a role that excludes an operation in NotActions, and is assigned a second role that grants access to the same operation, the user will be allowed to perform that operation. NotActions is not a deny rule – it is simply a convenient way to create a set of allowed operations when specific operations need to be excluded.
View a list of the built-in roles
You can use the Get-AzureRmRoleDefinition cmdlet to view a list of built-in roles:
1
2
3
4
5
6
7
|
Get-AzureRmRoleDefinition | Select-Object Name, Description
Name Description
---- -----------
API Management Service Contributor Can manage service and the APIs
API Management Service Operator Role Can manage service but not the APIs
API Management Service Reader Role Read-only access to service and APIs
Application Insights Component Contributor Can manage Application Insights components
|
View a list of the custom roles
You can view the list of custom roles (ones that you have created) available in the currently selected subscription by using the -Custom switch of the same cmdlet.
1
|
Get-AzureRmRoleDefinition -Custom
|
How to view the possible operations for a particular resource
When you are creating your own roles, you might want to see all the possible operations that can be permissioned for a particular resource type. In the example, below Microsoft.Sql/ represents Azure SQL Database and we use the Get-AzureRmProviderOperation cmdlet to search for all operations that begin with Microsoft.Sql/.
1
2
|
Get-AzureRmProviderOperation `
-OperationSearchString '*' | ? { $_.Operation -like 'Microsoft.Sql/*' } | select Operation,Description | Out-File azure-sql-permissions.txt
|
Creating a custom role
There are two ways to create a custom role .
- Write a role definition in JSON as shown in the Microsoft documentation; or
- If there is a built-in role close to what you need you can create a custom role based on an existing built-in (or indeed another custom role) and just modify the actions/notactions.
If you have a JSON role definition file you can create a new role definition using the command:
1
|
New-AzureRmRoleDefinition -InputFile my-role-definition-name.json
|
The PowerShell code below shows how you can create a custom role based on an existing one:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# Retrieve the role definition for the "Virtual Machine Contributor" built-in role
$role = Get-AzureRmRoleDefinition "Virtual Machine Contributor"
# Set the role Id to null as this will be automatically generated when we create a custom role
$role.Id = $null
# Give it a name and description
$role.Name = "My Limited VM Operator"
$role.Description = "Can monitor, stop, deallocate and restart virtual machines."
# Remove all actions in this case as we want to start fresh
# If you wanted to grant the default permissions for this role and add new permissions, you could skip this step.
$role.Actions.Clear()
$role.Actions.Add("Microsoft.Authorization/*/read")
$role.Actions.Add("Microsoft.Resources/subscriptions/resourceGroups/read")
$role.Actions.Add("Microsoft.Compute/*/read")
$role.Actions.Add("Microsoft.Compute/virtualMachines/start/action")
$role.Actions.Add("Microsoft.Compute/virtualMachines/restart/action")
$role.Actions.Add("Microsoft.Compute/virtualMachines/powerOff/action")
$role.Actions.Add("Microsoft.Compute/virtualMachines/deallocate/action")
$role.Actions.Add("Microsoft.Network/networkInterfaces/read")
$role.Actions.Add("Microsoft.Compute/disks/read")
$role.Actions.Add("Microsoft.Insights/alertRules/read")
$role.Actions.Add("Microsoft.Insights/diagnosticSettings/read")
# Clear the scopes that this applies to
$role.AssignableScopes.Clear()
# Apply it to a specific resource group, note you would need to replace with the actual subscription id
$role.AssignableScopes.Add("/subscriptions//resourceGroups/MyResourceGroup")
New-AzureRmRoleDefinition -Role $role
|
NOTE
There are two important points to be aware of when creating custom roles:
- A custom role defined in one subscription is not visible in other subscriptions.
- The role name must be unique to your Azure AD Tenant – e.g. if you want to use the same role definition across different subscription you will need to use a different name in each subscription – yes this is a pain and could cause some confusion.
Scopes
As you may have noticed from the code snippet above roles can be applied to multiple different scopes e.g. at the subscription level, resource group level or to an individual resource.
It is important to remember that access that you grant at parent scopes is inherited at child scopes.
Modifying an existing custom role
The simplest way to modify an existing custom role is by retrieving the role definition via Get-AzureRmRoleDefinition and storing it in a variable, then adding/removing actions or changing the scope as required, and finally applying the changes with Set-AzureRmRoleDefinition.
1
2
3
4
5
6
7
8
|
# Modify our custom role
$customRoleToModify = Get-AzureRmRoleDefinition -Name 'MyCustomAzureRBACRole'
# Remove the ability to grant/modify permissions
$customRoleToModify.Actions.remove('Microsoft.Authorization/*/write')
# Add the ability to read Azure Application Insights rules
$customRoleToModify.Actions.add('Microsoft.Insights/alertRules/*')
Set-AzureRmRoleDefinition -Role $customRoleToModify
|
Example custom roles
I have added a few example custom roles to my GitHub repo here:
https://github.com/vijayjt/AzureScripts/tree/master/rbac/role-definitions
The only thing you’d need to change is the assignable scopes in order to make use of the role definitions.
There are only two roles in the repo at the moment:
- A custom virtual machine operator role: I created this role to meet a requirement I had to allow particular users to start/stop/restart VMs in a particular resource group
- A custom limited subscription contributor role: this role was created to remove some types of sensitive operations from a subscription contributor. Of course what you deem as sensitive will change based on your context and the users involved. The custom role just adds sensitive operations into the NotActions. Ideally you should use more specific roles and scope the appropriately – but you may be asked to provide such broad access. One of the problems with this approach is new resource types are added frequently that may be sensitive so you have to constantly update the role definition.