January 24, 2023

How to let developers use Azure Service Bus Explorer and stay safe?

Choosing a tool which allows developers to manage messages in a dead-letter queue in Azure Service Bus, specifically allowing them to see, modify and resend messages, but not to make any changes to infrastructure. That was a dilemma we’ve faced not so long ago. First we thought about Azure Service Bus Explorer in the Portal, but it turned out to be not as easy as we hoped for… yet still totally possible!

Azure Service Bus Data Owner

Have you ever wondered about security implications of allowing developers, who claim they need access to Azure Service Bus Explorer (SBE)? Should they actually be able to see and use it? What if they do some stupid things, like deleting topics? Or maybe someone will break into their laptops and start messing with our infrastructure? Well, that all is an obvious thread to security especially on production.

First thing, that comes to mind when you try to restrict access, is to assign only Reader role. What a surprise it can be, when you suddenly see a message, that you need to have “Azure Service Bus Data Owner” to be able to use SBE. It is even mentioned in the documentation on Microsoft Learn.

Before we talk about final solution, let’s see what actions we can perform having Azure Service Bus Data Owner role. In the snippet below you can see, that as Owners we can basically perform ANY action (Microsoft.ServiceBus/*) on a Service Bus. Of course only on the resource, that you assign a user to.

For example assigning the role directly on a Service Bus is more dangerous than assigning it only on a Topic. Therefore if you decide to let a developer access one topic by giving him Azure Service Bus Data Owner rights he might not be able to delete your queue, but for sure he can delete topic or play around with it’s subscriptions, as well as modify RBAC assignments. We want to avoid it.

{
    "id": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419",
    "properties": {
        "roleName": "Azure Service Bus Data Owner",
        "description": "Allows for full access to Azure Service Bus resources.",
        "assignableScopes": [
            "/"
        ],
        "permissions": [
            {
                "actions": [
                    "Microsoft.ServiceBus/*"
                ],
                "notActions": [],
                "dataActions": [
                    "Microsoft.ServiceBus/*"
                ],
                "notDataActions": []
            }
        ]
    }
}

Crafting Custom Role Definition

First of all, define a new role that reflects build-in Azure Service Bus Data Owner – starting with below main.bicep file snippet. That’s a good starting point. Let us be creative and call the new role “AAAA Service Bus Deny Delete”, so it’s easy to find on the top of the list.

resource roleDef 'Microsoft.Authorization/roleDefinitions@2018-07-01' = {
  name: guid(subscription().id, 'Test Service Bus Deny Delete')
  properties: {
    roleName: 'AAAA Service Bus Deny Delete'
    description: 'AAAA Service Bus Deny Delete'
    type: 'customRole'
    permissions: [
      {
        actions: [
          'Microsoft.ServiceBus/*'
        ]
        notActions: []
        dataActions: [
          'Microsoft.ServiceBus/*'
        ]
      }
    ]
    assignableScopes: [
      subscription().id
    ]
  }
}

Next step, before we starting modifying file, is the deployment. We will perform the deployment on a subscription level so that it works on any AAD. In case you have P1 subscription or higher, you might want to consider deploying on a tenant level, so that it is available to all your subscriptions.

Now run the following Azure CLI command:

az deployment sub create --location westus --template-file main.bicep

Et voilà, our new role is there! If everything went smoothly now you should be able to see your role in Access Control tab.

View of all available roles. You can see your new role there. CONGRATULATIONS!

Removing unwanted actions

Now, that we have agreed upon what we don’t want our users to do and we know how to deploy, we will block some of unwanted actions (we had to analyse these first). Do that in not actions permissions in role definition by specifing notActions property to block actions ending with: delete, write and action.

notActions: [
  'Microsoft.ServiceBus/*/delete'
  'Microsoft.ServiceBus/*/write'
  'Microsoft.ServiceBus/*/action'
]

What we did here is basically taking everything, that was available to a Data Owner, and defining things we don’t want them to be able to do on a Service Bus resources. At the same time we still let users do all of the actions on data in dataActions section. Thanks to that they’ll be able to receive, send and peek messages.

Finally deploy the Bicep file again with az deployment command. You should be able to verify that there are only Read actions assigned to the role in UI.

Assigning Role and Testing

The last thing left, is to assign newly created role to your user and sleep peacefully. As now you can be sure, that your infrastructure is safe while developers can explore queue messages and fix all of the problems they’ve (probably) caused 😉

Is this the only possible solution?

Of course NOT! There’s at least one more I can think of, which is utilizing “Deny assignments” tab in Azure Portal. This option, however, requires using Azure Blueprints. You can read more about them here, but long story short in order to use that you’ll have to deploy your role on tenant level, which is only possible for Premium plans. Which not all of you can have access to while testing in your labs 🙂 But if you have a possibility, test it out and let me know in the comments how it went! 🙂

References

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.