This article will demonstrate a new way to control access for the blob service using the new Attribute-Based Access Control (ABAC) for Azure Blob storage.
When we want to access Azure blob storage, we could go to the control plane, get the access keys of the storage account, and then with the access key, we can authenticate to the data plane to get access to the content. We could also get a shared access signature (SAS), which is a more granular set of access that is signed with the access keys of the storage account. However, this way of access is very generic and overpowered!
Table of Contents
One of the storage security best practices is to limit the exposure of the access keys as much as possible. Because when you use shared access signatures to get access to your data, you should be aware of two potential risks:
- If a SAS is compromised, it can be used by anyone who obtains it.
- If a SAS provided to a client application expires and the application is unable to retrieve a new SAS from your service, then the application’s functionality may be hindered.
The good news is that you can now disable access keys for your storage account from the configuration blade as shown in the figure below, so any requests to the account that are authorized with access keys, including shared access signatures (SAS), will be denied. Because suppose rogue admins left a company but still have the access keys at hand, they cannot use them for inappropriate authentication against public exposed storage accounts after their Azure AD accounts have been disabled.
To move away from using the storage account access key is the integration with Azure AD and role-based access control (RBAC). And for many cases where storage accounts are publicly exposed, this might be a good option because it forces users to authenticate with Azure AD accounts to access the data.
Now, with the introduction of all-based access control for storage, we can take further actions for both the control plane and the data plane. If we look at the Identity and Access Management (IAM) blade for an Azure storage account and/or on the container level under Roles, we actually see there are several roles such as “Storage Blob Data Owner”, “Storage Blob Data Reader”, “Storage Blob Delegators”, and “Storage Blob Data Contributor” as shown in the figure below.
If we go and look at one of these special roles under View details (for example, Storage Blob Data Owner), we can see there are Actions, so these are the regular control planes that we can perform (Read, Write, and Delete container, etc). But we can also see Data Actions, this is now operating at the data plane. We can Read blob, Write blob, Delete blob, and Add blob content as shown in the figure below.
But with the new attribute-based access control, we can actually go even more granular. In this article, we will show you how to leverage attribute-based access control (ABAC) for the Azure blob service.
To follow this article, you need to have the following:
1) Make sure you have an active Azure subscription. If you don’t have a subscription, you can create a free one here.
2) Azure storage account General Purpose v2 (GPv2) only, but you can upgrade any GPv1 account to a GPv2 account – To create a GPv2 storage account, you can follow the instructions described here.
3) One or more storage containers created with a couple of blobs uploaded – To create a container and upload a blob, you can follow the instructions described here.
4) Azure Storage integration with Azure AD identity-based authorization. Please note that you must have the Storage Blob Data Owner to be able to switch the authentication method from Access key to Azure AD User Account.
5) Last because the blob index tags are only in public preview at the time of this writing, you’ll need to register your subscription before you can use this feature. Launch Azure Cloud Shell and run the following PowerShell command:
Register-AzProviderFeature -FeatureName BlobIndex -ProviderNamespace Microsoft.Storage Register-AzResourceProvider -ProviderNamespace Microsoft.Storage
If you prefer the Azure CLI, you can register your subscription for the blob index tags by running the following command:
az feature register --namespace Microsoft.Storage --name BlobIndex az provider register --namespace 'Microsoft.Storage'
At the time of this writing, the public preview for the blob index for the Azure storage account is available in the following 35 regions only. It will soon be available in all regions.
East US East US 2 West US West Europe East Asia Southeast Asia Japan East Japan West North Central US South Central US Central US North Europe Brazil South Australia East Australia Southeast South India Central India West India Canada East Canada Central West US 2 West Central US UK South UK West Korea Central Korea South France Central Australia Central South Africa North UAE North Switzerland North Germany West Central Norway East East US 2 EUAP Central US EUAP
Enable Attribute-Based Access Control
To enable attribute-based access control (ABAC) for Azure Blob storage, you need to add an ABAC condition to a new or existing Azure role assignment.
At a high level, we take the identity first from Azure AD, combine it with the role assignment (Blob data reader as an example), and then we assign it at the scope level which could be a storage account, resource group, subscription, or a management group, but now we can also add attribute-based access control (ABAC) conditions to access the blob. And as part of those conditions, we can say, are we looking at the resource or are we looking at the request of what the user is actually performing? and then only if the condition is met, does he gets the role defined that has the actions like (Read, write, or delete blob) that we could normally do on the resource?
This is best understood with an example:
Let’s imagine we have a user, named “Joe” and I am an Azure subscription owner. Joe is a member of an Azure AD security group named “Human Resource”, and that group is going to be given the role of Blob data reader, but we are going to set a condition to say, he only has that role if there is a tag on the blob of Key equal to “project” and Value equal to “HR”. So he can read blobs with the index tag “HR”, but he won’t be able to read other blobs even though the assignment of the Blob data reader is set at the scope level (storage account, resource group, or subscription).
So let’s see how to do this.
Step 1: Set the Blob index tag
Assuming you have all the prerequisites in place, take now the following steps to set the blob index tag key of “project” and a tag value of “HR”. You can think of the Blob index tags as key-value pairs.
Navigate to your storage account, select your container, and then select the desired blob(s). On the Overview tab, scroll down and set the Blob index tags as shown in the figure below, and then click Save.
Step 2: Set the Attribute-Based Access Control condition
In this step, we will navigate to the role assignment, select the actions to which the condition should apply, and finally add the expression.
Browse to your storage account > Access Control (IAM) blade, click +Add, and then choose to Add role assignment (Preview).
In this example, on the Add role assignment page, I will select “Storage Blob Data Reader” as shown in the figure below. Click Next to continue.
On the Members page, add the security group, user, or service principal you want to give access to as shown in the figure below. Click Next to continue.
Then on the Condition page, we can set the condition by selecting +Add condition. Then add the action type by clicking on Select actions as shown in the figure below. In this example, I will select “Read content from a blob with tag conditions“.
Then we can build the expression by selecting the +Add expression.
As shown in the figure below, the Attribute source is set to “Resource”, then for the Attribute, select “Blob index tags [Values in key]”, the tag Key is “project” in this example (please note that this is case sensitive), then for the Operator select “StringEqualsIgnoreCase”, I am ignoring the value here, and then set the tag Value based on your case. In this example, the value must be “HR”. Click Save.
Please note that you can create the expression in the UI, or you can do it directly in code as shown in the figure below.
Click Next to continue, and finally click Review + assign to finish adding the ABAC condition to the role assignment.
Step 3: Validate the access
In the final step, we will validate the access for the user “Joe” by accessing the storage account and trying to read/download the blob named “HR_May2021_Doc3”. Remember this file has the project set to “HR” as described in the previous step. As shown in the figure below, we can see the metadata, which means he has access to the data plane and he could download it, so this worked!
Now I have other two blobs “HR_May2021_Doc1”, and “HR_May2021_Doc2” that do not have that blob index tags set, so “Joe” should not have access. If he tries to click on a different one. The authorization will fail as shown in the figure below!
Because the condition is not met, the blob does not have that project Blob index tags set to “HR”, so he doesn’t have access. So even though the role assignment was at the storage account. The project has to match what that condition was.
In the previous example, the Blob index tags value was set on the blob level, however, you can also set them at the container level, so you can force the user to set these tags on blob upload as well. In this case, you set the role assignment for the security group as “Storage Blob Data Owner” at the container level, because it requires a Blob index tag to be created and only Owners can actually create Blob index tags and not Contributors.
You set the Attribute-Based Access Control condition for the role assignment with the following data actions as shown in the figure below.
- Data Action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write
- Operation: Write to a blob with blob index tags
- Data Action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/add/action
- Operation: Write to a blob with blob index tags
Then you create and build the expression with the request attributes as shown in the figure below.
The Attribute source is set to “Request”, then for the Attribute, select “Blob index tags [Values in key]”, the tag Key is “project” in this example (please note that this is case sensitive), then for the Operator select “StringEquals”, and then set the tag Value based on your case. In this example, the value must be “HR”.
Now, when the user tries to upload a blob to the container, it will fail as shown in the figure below. Because he didn’t set the tag key. We are requiring the blob to have an index tag set.
To set the blob index tag on upload, you need to expand Advanced when selecting to upload a file, and then set the index tag keys as shown in the figure below and then click Upload.
The upload will work now because we are meeting the condition that gives the user the role that lets him create the blob and set those index tags. So that’s kind of the key point of these attribute-based access controls, so only he gets the role if the conditions are met.
It’s also worth mentioning that you can exclude a virtual directory within the container from the blob index tag.
To do this, you first assign the role for the user at the storage account and/or on the container level, and then you create an attribute-based access control (ABAC) condition with Data Action (Read a blob for example) as shown in the figure below.
Then you build two expressions with an attribute of the “Resource”. In the first expression, you specify the container name, in this example, it has to be “blob-hr-container01”, and a second expression with the path of the Blob as an attribute, and it has to include the “HRRead/*” through a virtual directory. Please note that blobs don’t actually have true folders, but we can do virtual directories, it’s just made part of the name of the Blob. In this example, the blob path has to include an “HRRead/*” as shown in the figure below.
Now remember from the previous example, the user “Joe” couldn’t access the blob which didn’t have a tag and it’s not in the HRRead virtual folder. This time to get a Blob reader, it’s going to have to match the condition with the expression, so it should be in the “blob-hr-container01” container and the path includes “HRRead/*”, which it’s true in this case as shown in the figure below.
That’s it there you have it!
In this article, we showed you how to use the new Attribute-Based Access Control (ABAC) for Azure Blob storage, so you can control the access to your data with even more granularity.
The new attribute-based access control (ABAC) is an authorization strategy that defines access levels based on attributes associated with security principles, resources, requests, and the environment. Azure ABAC builds on role-based access control (RBAC) by adding conditions to Azure role assignments in the existing identity and access management (IAM) system.
At the time of this writing, the only caveat I would say is potential readability, because if we just set the rules at the subscription level or resource group within the storage account and then use things like the Blob index tag role as demonstrated in this article. If we just go and look at the user “Joe” rights, for example, we will see a Storage Blob Data Reader only as shown in the figure below. It doesn’t show us the conditions that we just created, or try to evaluate what are the effective rights, which may get a little bit confusing, so naming things is important here, but just bear that in mind when you’re leveraging that.
Attribute-Based Access Control is a game-changer. It’s in public preview at the time of this writing, and it includes support for role assignment conditions on Blobs and Azure Data Lake Storage (ADLS) Gen2 and enables you to author conditions based on resource and request attributes. I think we’re going to see functionality added and this is going to grow.
I highly recommend you checking the Microsoft documentation here, it has actual code you can copy and paste into the code view. Attribute-Based Access Control gives us the ability now to add conditions for the role to actually be assigned whatever scope, which I think is super useful.
Thank you for reading my blog.
If you have any questions or feedback, please leave a comment.