Create a custom RBAC in Azure

This post demonstrates how to create a custom role. The best practice for creating custom roles is to base it on an existing role.

https://docs.microsoft.com/en-us/azure/role-based-access-control/tutorial-custom-role-powershell

Custom roles need to be created using either Azure CLI or PowerShell. You cannot create a Custom role using the Azure Portal. As of 2019, the template for creating an RBAC role looks like:

{
  "Name": "Virtual Machine Operator",
  "Id": "88888888-8888-8888-8888-888888888888",
  "IsCustom": true,
  "Description": "Can monitor 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.ResourceHealth/availabilityStatuses/read",
    "Microsoft.Resources/subscriptions/resourceGroups/read",
    "Microsoft.Insights/alertRules/*",
    "Microsoft.Insights/diagnosticSettings/*",
    "Microsoft.Support/*"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/{subscriptionId1}",
    "/subscriptions/{subscriptionId2}",
    "/subscriptions/{subscriptionId3}"
  ]
}

Some important things to note here:

  1. IsCustom attribute will always be true.
  2. Actions are Azure resource actions that can be executed, e.g. Create, Read, Update Delete a Virtual Machine.
  3. You need to be the subscription Owner or the subscription user administrator in order to have the correct permissions to create a custom role.

To get the list of Actions (Resource Provider Operations) you can execute the following commands in either Azure CLI or PowerShell.

Azure CLI

az provider operations list

PowerShell

Get-AzureRMProviderOperation

Create a custom support role

In this demo I’ll create a custom Microsoft support role that allows anyone with this role to manage support tickets. The steps are:

  1. Get the ID of the Subscription
  2. Review the list of Resource Provider Operations
  3. Output the template JSON file
  4. Edit the JSON file with Microsoft Visual Studio Code
  5. Add the Subscription ID
  6. Add permissible Actions to this role
  7. Cleanup tasks
  8. Deploy the Custom Role

*For this custom role creation, I’ll be using PowerShell.

1. Get the ID of the Subscription

All custom roles require a scope. A scope in this context is the subscription the custom role will be attached to. For the RBAC template we’ll need to specify the subscription ID.

Get-AzureRmSubscription
PS Azure:\> Get-AzureRmSubscription

Name                  Id                                   TenantId                             State
----                  --                                   --------                             -----
MSDN DEV Subscription b6282717-222f-4ce3-998a-5262812768d2 dcd1f5f0-289f-4a92-83a4-66ff22350d8c Enabled


Azure:/
PS Azure:\>

2. Review the list of Resource Provider Operations

In this example, I’ll be using checking which Operations exist under Microsoft.Support. I also want to return the columns Operation and Description.

Get-AzProviderOperation "Microsoft.Support/*" | FT Operation, Description -AutoSize

3. Output the template JSON file

We’ll be making changes to a JSON file which will become the RBAC definition. To do this we need to output and edit a JSON file:

Get-AzRoleDefinition -Name "Reader" | ConvertTo-Json | Out-File $home/clouddrive/CustomRolesReaderSupportRole.json

Verify that the file has been written to the clouddrive:

ls
cd $home/clouddrive

4. Edit the JSON file with Microsoft Visual Studio Code

code CustomRolesReaderSupportRole.json

The output of the file should be:

{
  "Name": "Reader",
  "Id": "acdd72a7-3385-48ef-bd42-f606fba81ae7",
  "IsCustom": false,
  "Description": "Lets you view everything, but not make any changes.",
  "Actions": [
    "*/read",
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/"
  ]
}

5. Add the Subscription ID

Copy the subscription ID from step 1 and place this into the AssignableScopes.

{
  "Name": "Reader",
  "Id": "acdd72a7-3385-48ef-bd42-f606fba81ae7",
  "IsCustom": false,
  "Description": "Lets you view everything, but not make any changes.",
  "Actions": [
    "*/read",
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/b6282717-222f-4ce3-998a-5262812768d2"
  ]
}

6. Add permissible actions to this role

Finally add additional actions that this role will have permissions to commit. A list of Resource Provider Operations can be found here: https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations

{
  "Name": "Reader",
  "Id": "acdd72a7-3385-48ef-bd42-f606fba81ae7",
  "IsCustom": false,
  "Description": "Lets you view everything, but not make any changes.",
  "Actions": [
    "*/read",
    "Microsoft.Support/*"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/b6282717-222f-4ce3-998a-5262812768d2"
  ]
}

7. Cleanup JSON file

Remove the Id line and replace the ‘false‘ with ‘true‘ for IsCustom.

{
  "Name": "Reader",
  "IsCustom": true,
  "Description": "Lets you view everything, but not make any changes.",
  "Actions": [
    "*/read",
    "Microsoft.Support/*"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/b6282717-222f-4ce3-998a-5262812768d2"
  ]
}

At this point you are ready to save the files changes in Visual Studio Code. Hit Ctrl + S to save the JSON file.

8. Deploy the custom role

Now that we have the definition, it’s time to instantiate this role. In PowerShell execute the following:

New-AzRoleDefinition -InputFile "$home/clouddrive/CustomRolesReaderSupportRole.json"

Output should be similar to this:

PS /home/syed/clouddrive> New-AzRoleDefinition -InputFile "$home/clouddrive/CustomRolesReaderSupportRole.json"

Name             : Reader Support Tickets
Id               : 0f80dce9-9487-4881-a581-8fab19bb4dde
IsCustom         : True
Description      : Lets you view everything, but not make any changes.
Actions          : {*/read, Microsoft.Support/*}
NotActions       : {}
DataActions      : {}
NotDataActions   : {}
AssignableScopes : {/subscriptions/b6282717-222f-4ce3-998a-5262812768d2}

Validation of custom roles

When creating custom roles you need to be careful about the permissions a user will be granted with using your new custom role. You have two options here:

  1. Graceful degradation – this is where you first add as many Actions as you think is necessary in order for the user to complete their task, then you gradually remove permissions that the user does not need over time.
  2. Progressive enhancement – add a minimum number of Actions, and extend the role with new permissions when necessary.

Both approaches have their pros and cons, but one way to ensure that custom roles do not present a security risk over time is to plan regular reviews of both built-in and custom roles. To do this, go to:

Dashboard > Subscriptions > {your subscription} > Access control (IAM)Permissions

In this example, search for the new support role that you created previously.

Note that clicking on the role will not reveal the permissions. You will need to click on the ellipsis. At this point if you scroll down the long list until you find a reference to Management set to All.

You are now able to drill down further to understand the exact permissions this role has:

Audit an existing role

You can speed up any auditing by using PowerShell to extract the JSON of any built-in or custom role. For instance, if I wanted to review the Owner role:

1. Extract the role definition and save as a file called: AuditOwnerRole.json

Get-AzRoleDefinition -Name "Owner" | ConvertTo-Json | Out-File $home/clouddrive/AuditOwnerRole.json

Note: Changes to a role are logged in the Activity Log. These are retained for 90 days.

2. Open the file up with Microsoft Visual Studio Code

code $home/clouddrive/AuditOwnerRole.json

3. The output JSON should now be presented for review

{
  "Name": "Owner",
  "Id": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
  "IsCustom": false,
  "Description": "Lets you manage everything, including access to resources.",
  "Actions": [
    "*"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/"
  ]
}

A list of built-in roles provided by Microsoft can be found here: https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles

Leave a comment