Skip to main content
Jorge Bernhardt Jorge Bernhardt
  1. Posts/

Bicep - Azure Custom Roles Definitions

·957 words·5 mins· 100 views · 5 likes ·
Azure CLI Azure Role-based Access Control (RBAC) Microsoft Microsoft Azure

Hello everyone! Today, I want to talk about custom roles in Azure. Azure gives us many roles to use, but sometimes, they don’t do exactly what we want. So, we need to make our own roles that do the exact job.

To streamline our custom role deployments, we’re turning to Bicep. For those unfamiliar, Bicep is Azure’s domain-specific language designed to simplify the process of working with ARM templates. It offers cleaner code, improved readability, and a more intuitive way to define and deploy Azure resources.

In this article, I’ll guide you through creating and deploying custom roles using Bicep, ensuring that your Azure environments have the exact permissions they require. Let’s get started!

Prerequisites>

Prerequisites #

Before you start, you’ll need the following to deploy and manage a budget resource with Bicep:

  • You need Azure CLI version 2.20.0 or later to deploy Bicep files on your local machine.
  • A text editor or IDE of your choice (Visual Studio Code with Bicep extension is my recommendation)
Create the Bicep files>

Create the Bicep files #

The first step in deploying a Bicep template is to create the Bicep file that defines your resources. Create a new file named customroles.bicep. This file will contain the necessary code to define and configure your Azure custom roles.

targetScope= 'subscription'

// Input parameter
param roles array

// Define the role resources based on the input
resource roleDefinitions 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' = [for role in roles: {
  name: guid(role.roleName)
  properties: {
    roleName: role.roleName
    description: role.description
    type: 'CustomRole'
    assignableScopes: [
      subscription().id
    ]
    permissions: role.permissions
  }
}]

// Output the names and IDs of the deployed roles
output deployedRoleNames array = [for i in range(0, length(roles) - 1): roleDefinitions[i].properties.roleName]
output deployedRoleIds array = [for i in range(0, length(roles) - 1): roleDefinitions[i].id]

Important: In our Bicep file, we have a parameter named roles. This parameter is expected to be an array, where each item represents a custom Azure role that we want to create. Let’s break down what each role should have:

  • roleName: This is a string that defines the name of the custom role.
  • description: A brief string that describes what the role does.
  • permissions: This is an array that specifies what actions the role can and cannot perform. Inside this, we have:
    • actions: List of actions that the role can perform.
    • notActions: List of actions the role cannot perform.
    • dataActions: List of data-related actions the role can perform.
    • notDataActions: List of data-related actions the role cannot perform.

Here’s a template for the roles:

roles: [
  {
    roleName: "Custom_role_name",
    description: "Some description that helps understand the purpose of the role",
    permissions: [
      {
        actions: [],
        notActions: [],
        dataActions: [],
        notDataActions: []
      }
    ]
  }
]
Deployment scope>

Deployment scope #

In Bicep, you have the flexibility to target your deployment toward multiple scopes, such as a resource group, subscription, or management group. In this case, when we define Azure custom roles, the valid deployment scopes are resource, subscription, and management groups.

For this example, I’ll use a subscription as the scope.

Deploy the Bicep template using the Azure CLI>

Deploy the Bicep template using the Azure CLI #

Once your Bicep template is prepared, and you’ve selected your desired scope, you can proceed to deploy the template through the Azure CLI. To do so, execute the following commands.

Parameters>

Parameters #

Personalization is key to making your template reusable. With the parameters, you can easily tailor the template to your specific needs. You can use either inline parameters or a parameter file to pass parameter values. In my case, I will use a file to pass the parameters; here is an example.

{
    "roles": {
      "value": [
        {
          "roleName": "Custom_VM_Operator",
          "description": "Can monitor and restart virtual machines",
          "permissions": [
            {
              "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": []
            }
          ]
        },
        {
          "roleName": "Custom_FileShare_Data_Reader",
          "description": "Allows for reading data and metadata from Azure file shares.",
          "permissions": [
            {
              "actions": [
                "Microsoft.Storage/storageAccounts/fileServices/shares/read",
                "Microsoft.Storage/storageAccounts/fileServices/read",
                "Microsoft.Storage/deletedAccounts/read",
                "Microsoft.Storage/storageAccounts/read",
                "Microsoft.Storage/storageAccounts/listkeys/action"
              ],
              "notActions": [],
              "dataActions": [
                "Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read"
              ],
              "notDataActions": []
            }
          ]
        },
        {
          "roleName": "Custom_ResourcePolicy_Reader",
          "Description": "Permite la lectura de políticas de recursos y sus asignaciones en Azure.",
          "permissions": [
            {
              "actions": [
                "Microsoft.Authorization/policyAssignments/read",
                "Microsoft.Authorization/policyDefinitions/read",
                "Microsoft.Authorization/policySetDefinitions/read",
                "Microsoft.Management/managementGroups/read",
                "Microsoft.Resources/subscriptions/resourceGroups/read",
                "Microsoft.Resources/subscriptions/resourceGroups/resources/read"
              ],
              "notActions": [],
              "dataActions": [],
              "notDataActions": []
            }
          ]
        },
        {
          "roleName": "Custom_Tag_Manager",
          "description": "Can read resource groups and manage their tags.",
          "permissions": [
            {
              "actions": [
                "Microsoft.Resources/subscriptions/resourceGroups/read",
                "Microsoft.Resources/subscriptions/resourceGroups/resources/read",
                "Microsoft.Resources/tags/read",
                "Microsoft.Resources/tags/write",
                "Microsoft.Resources/tags/delete"
              ],
              "notActions": [],
              "dataActions": [],
              "notDataActions": []
            }
          ]
        }
      ]
    }
  }

Important: Please note that the parameter file stores parameter values in plain text format. If you need to include a parameter with sensitive data, it’s recommended to store the value in a secure key vault.

Preview changes>

Preview changes #

Before deploying a Bicep file, you can preview the changes that will occur to your resources. Using what-if operations does not change existing resources; it simply shows you an output that includes color-coded results that allow you to see different changes.

az deployment sub what-if \
--template-file <filename>.bicep \
--parameters @<filename>.paramaters.json \
--location <location>
Deploy the Azure resource>

Deploy the Azure resource #

Finally, to deploy the template, run the following command.

az deployment sub create \
--template-file <filename>.bicep \
--parameters @<filename>.paramaters.json \
--location <location>
Validate the deployment>

Validate the deployment #

To verify that the changes have been applied correctly, you can use the Azure portal or the command line tools. For the Azure CLI for example, use the following command.

az role definition list \
--custom-role-only true \
--output table

References and useful links #

Thank you for taking the time to read my post. I sincerely hope that you find it helpful.