Search code examples
pythonazureazure-storageazure-blob-storageazure-security

How to generate SAS URLs for blob storage using User Delegation Key in Python


I'm trying to generate SAS URLs to read blobs using a user delegation key and the Azure SDK for Python.

The following code works if I use the storage account key but fails if I try to use the user delegation key.

import datetime as dt
import json
import os
from azure.identity import DefaultAzureCredential
from azure.storage.blob import (
    BlobClient,
    BlobSasPermissions,
    BlobServiceClient,
    generate_blob_sas,
)

credential = DefaultAzureCredential(exclude_shared_token_cache_credential=True)
    
storage_acct_name = "XYZ_storage_account"
container_name = "XYZ_blob_container"
blob_name = "xyz_data.json"

url = f"https://{storage_acct_name}.blob.core.windows.net"
blob_service_client = BlobServiceClient(url, credential=credential)
udk = blob_service_client.get_user_delegation_key(
    key_start_time=dt.datetime.utcnow() - dt.timedelta(hours=1),
    key_expiry_time=dt.datetime.utcnow() + dt.timedelta(hours=1))

sas = generate_blob_sas(
    account_name=storage_acct_name,
    container_name=container_name,
    blob_name=blob_name,
    user_delegation_key=udk,
    #account_key=os.getenv("STORAGE_ACCOUNT_ACCESS_KEY"),
    permission=BlobSasPermissions(read=True),
    start = dt.datetime.utcnow() - dt.timedelta(minutes=15),
    expiry = dt.datetime.utcnow() + dt.timedelta(hours=2),
)

sas_url = (
    f'https://{storage_acct_name}.blob.core.windows.net/'
    f'{container_name}/{blob_name}?{sas}'
)

blob_client = BlobClient.from_blob_url(sas_url)
blob_data = blob_client.download_blob(encoding='UTF-8')
data = json.loads(blob_data.readall())

Using the UDK, I get the following error:

“This request is not authorized to perform this operation using this permission. ... ErrorCode:AuthorizationPermissionMismatch”

Having the storage account key floating around is non-ideal for security, so I'd much rather use the UDK.

In the Azure portal, I can view storage account | Access Control (IAM) | View My Access and see that I have role “Contributor”, scope “Subscription (Inherited)”.

It looks like from the docs that “Contributor” should give the require “generateUserDelegationKey” permission, but... 🙄


Solution

  • As mentioned in the comments, in order for a SAS token obtained via user delegation key, the user should have appropriate data related RBAC role for the storage account.

    The reason you got this error is because the user is assigned a Contributor role which is a control plane RBAC role. Control plane RBAC roles are meant to manage the resources (like storage accounts themselves) and not the data inside them. For managing data, a user must be assigned appropriate data RBAC role.

    More information about these roles can be found here: https://learn.microsoft.com/en-us/azure/storage/blobs/assign-azure-role-data-access?tabs=portal.