When working with Azure, Blob Storage is frequently used. This article documents several common approaches for accessing Blob Storage from applications running in production environments:

一、Accessing Blob Storage via a Microsoft Entra ID Application Account

Advantages:

  • Works outside Azure environments (e.g., on-premises servers, AWS EC2)
  • Supports cross-subscription and cross-tenant access

Disadvantages:

  • Secrets must be securely stored (e.g., in Azure Key Vault)
  • Manual secret rotation is required upon expiration; otherwise, the application will break
  • Risk of credential leakage, especially if secrets are hardcoded in CI/CD pipelines

The specific configuration is as follows:

1、Configure an Application-Specific Account

Register an application in Entra ID, create a service principal, generate a client secret or certificate, and assign the application the Storage Blob Data Contributor role (for read/write access). Record the following information:

Tenant ID
Client ID
Client Secret (expires after a set period—manual renewal required)

2、Grant Blob Storage Permissions to the Application

(1)In the Azure portal, navigate to your storage account (e.g., mdblob001).

(2)Go to Access control (IAM) → + Add → Add role assignment.

(3)Select the role: Storage Blob Data Contributor (grants read & write access to blobs). Under Assign access to, choose User, group, or service principal, search for your app name (e.g., MyBlobApp), select it, and click Review + assign.

3、Access Blob Storage from Application Code

Use ClientSecretCredential (or ClientCertificateCredential) in your code to obtain tokens. Below is a Python SDK example:

Install required packages:

1
pip install azure-identity azure-storage-blob
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from azure.identity import ClientSecretCredential
from azure.storage.blob import BlobServiceClient

# Entra ID App Configuration
TENANT_ID = "3c4e99f3-4831-4352-ae86-4d8f59512865"
CLIENT_ID = "3357a2b1-9895-484d-8754-42c162f2c9eb"
CLIENT_SECRET = "DoB8Q~4Gwl6sdzV_ocfUvXA3BtHYJLgrimwwMcj1"

# Storage Account & File Info
ACCOUNT_NAME = "mdblob001"
LOCAL_FILE_PATH = "/mnt/d/file.txt"
BLOB_NAME = "uploaded-file.txt"
CONTAINER_NAME = "mycontainer"  # Ensure this is defined

# Obtain Token Credential
credential = ClientSecretCredential(
    tenant_id=TENANT_ID,
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET
)

# Create Blob Service Client
blob_service_client = BlobServiceClient(
    account_url=f"https://{ACCOUNT_NAME}.blob.core.windows.net",
    credential=credential
)

# List containers (test permissions)
try:
    containers = blob_service_client.list_containers()
    for container in containers:
        print("Container:", container.name)
except Exception as e:
    print("Error:", e)

# Upload file
try:
    blob_client = blob_service_client.get_blob_client(
        container=CONTAINER_NAME,
        blob=BLOB_NAME
    )

    with open(LOCAL_FILE_PATH, "rb") as data:
        blob_client.upload_blob(data, overwrite=True)

    print(f"File '{LOCAL_FILE_PATH}' successfully uploaded as '{BLOB_NAME}'")

except FileNotFoundError:
    print("Local file not found")
except Exception as e:
    print("Upload failed:", e)

二、Accessing Blob Storage via AKS System-Assigned Managed Identity

Azure provides system-assigned managed identities—automatically managed service principals—for supported resources like VMs, AKS clusters, and App Services. AKS enables this by default.

Advantages:

  • Lifecycle automatically managed (created/destroyed with the AKS cluster)
  • No secrets to manage—fully keyless access
  • Higher security: credentials never appear in code, config files, or environment variables
  • Deep integration with Azure RBAC
  • SDKs only need DefaultAzureCredential to auto-acquire tokens

Disadvantages:

  • Cannot be reused across workloads with different permission requirements
  • RBAC assignments must be configured manually
  • Not portable across clouds
  • Naming is not customizable

1、Enable system-assigned managed identity for AKS cluster

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
az aks create --resource-group test --name md-test-southafrica --generate-ssh-keys  # Enable system-assigned managed identity only for new clusters
az aks update --resource-group test --name md-test-southafrica --enable-managed-identity  # For existing clusters
az aks show --resource-group test -n md-test-southafrica --query "identity"  # View the system-assigned managed identity
{
  "delegatedResources": null,
  "principalId": "37e6bf32-b18d-4e3a-9f97-b86d0c9dc2cf",
  "tenantId": "3c4e99f3-4831-4352-ae86-4d8f59512865",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

2、Assign Blob Storage Role to the Managed Identity

Roles:

  • Storage Blob Data Reader: read-only
  • Storage Blob Data Contributor: read/write
  • Storage Blob Data Owner: read/write + ACL management (for ADLS Gen2)

Use Azure CLI to grant the identity access to Blob Storage (for example, the Storage Blob Data Contributor role):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Get the storage account ID
STORAGE_ACCOUNT_ID=$(az storage account show -n mdblob001 -g test --query id -o tsv)
echo $STORAGE_ACCOUNT_ID
/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001

# Assign the role
AKS_PRINCIPAL_ID=$(az aks show --resource-group test --name md-test-southafrica --query "identity.principalId" --output tsv)
echo "AKS Principal ID: $AKS_PRINCIPAL_ID"
AKS Principal ID: 37e6bf32-b18d-4e3a-9f97-b86d0c9dc2cf

az role assignment create \
  --assignee "37e6bf32-b18d-4e3a-9f97-b86d0c9dc2cf" \
  --role "Storage Blob Data Contributor" \
  --scope "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001"
# Grant permissions to the AKS system-assigned managed identity

{
  "condition": null,
  "conditionVersion": null,
  "createdBy": "dc8278a7-78d6-4f6e-971c-8974d0ac4e2f",
  "createdOn": "2025-02-19T04:31:42.582306+00:00",
  "delegatedManagedIdentityResourceId": null,
  "description": null,
  "id": "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001/providers/Microsoft.Authorization/roleAssignments/81f9e7d1-b83c-4c4b-aab0-047fc4fb525f",
  "name": "81f9e7d1-b83c-4c4b-aab0-047fc4fb525f",
  "principalId": "37e6bf32-b18d-4e3a-9f97-b86d0c9dc2cf",
  "principalName": "ad674b19-a3b1-47ed-9463-128289ae5e34",
  "principalType": "ServicePrincipal",
  "resourceGroup": "Test",
  "roleDefinitionId": "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe",
  "roleDefinitionName": "Storage Blob Data Contributor",
  "scope": "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001",
  "type": "Microsoft.Authorization/roleAssignments",
  "updatedBy": "dc8278a7-78d6-4f6e-971c-8974d0ac4e2f",
  "updatedOn": "2025-02-19T04:31:42.582306+00:00"
}

az role assignment list \
  --scope "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001" \
  --output table
# List role assignments under the storage account

Principal                             Role                           Scope
--------------------------------------------------------------------------------
ad674b19-a3b1-47ed-9463-128289ae5e34  Storage Blob Data Contributor  /subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001

3、Verification

Use the Python SDK to build a container and verify access:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from azure.storage.blob import BlobServiceClient
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
    account_url="https://mdblob001.blob.core.windows.net",
    credential=credential
)

# List containers
containers = blob_service_client.list_containers()
for c in containers:
    print(c.name)

DefaultAzureCredential automatically attempts multiple authentication methods and, in AKS, retrieves a token via IMDS (Instance Metadata Service), provided that the pod is running on a node with managed identity enabled.

三、Accessing Blob Storage via AKS User-Assigned Managed Identity with Workload Identity

This is Microsoft’s recommended, standards-based (OIDC), secure approach for fine-grained workload identity.

1、Create a User-Assigned Managed Identity

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
az group create -n rg-aks-wi -l test  # Create a resource group; skip if it already exists
az identity create --name MD-Blob-Identity --resource-group test  # Create a user-assigned managed identity
{
  "clientId": "7d9b65f6-959d-4a74-ab3f-67d16adc8c37",
  "id": "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourcegroups/test/providers/Microsoft.ManagedIdentity/userAssignedIdentities/MD-Blob-Identity",
  "location": "southafricanorth",
  "name": "MD-Blob-Identity",
  "principalId": "bdd58864-063f-451d-b352-2dded3582b36",
  "resourceGroup": "test",
  "systemData": null,
  "tags": {},
  "tenantId": "3c4e99f3-4831-4352-ae86-4d8f59512865",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

# Retrieve key information
export USER_ASSIGNED_CLIENT_ID="$(az identity show -g test -n MD-Blob-Identity --query clientId -o tsv)"
export USER_ASSIGNED_PRINCIPAL_ID="$(az identity show -g test -n MD-Blob-Identity --query principalId -o tsv)"

2、Assign Blob Storage Permissions

1
2
3
4
5
6
7
STORAGE_ACCOUNT_ID=$(az storage account show -n mdblob001 -g test --query id -o tsv)
echo $STORAGE_ACCOUNT_ID
/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourceGroups/Test/providers/Microsoft.Storage/storageAccounts/mdblob001
az role assignment create \
  --role "Storage Blob Data Contributor" \
  --assignee $USER_ASSIGNED_PRINCIPAL_ID \
  --scope $STORAGE_ACCOUNT_ID

3、Enable Workload Identity on AKS (if not already enabled)

1
2
az aks update -g test -n md-test-southafrica --enable-oidc-issuer
export AKS_OIDC_ISSUER=$(az aks show -g test -n md-test-southafrica --query "oidcIssuerProfile.issuerUrl" -o tsv)

4、Federate the Identity with a Kubernetes ServiceAccount

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Get the client ID of the user-assigned identity
export USER_ASSIGNED_CLIENT_ID=$(az identity show -g test -n MD-Blob-Identity --query clientId -o tsv)

# Create a federated credential (allowing a specific ServiceAccount in AKS to use this identity)
az identity federated-credential list --resource-group test --name md-test-southafrica

az identity federated-credential create --name my-fed-cred \
  --identity-name MD-Blob-Identity \
  --resource-group test \
  --issuer $AKS_OIDC_ISSUER \
  --subject system:serviceaccount:demo:md-blob-sa \
  --audience api://AzureADTokenExchange

{
  "audiences": [
    "api://AzureADTokenExchange"
  ],
  "id": "/subscriptions/cdab1cd0-0556-41bc-8905-33ce907e818a/resourcegroups/test/providers/Microsoft.ManagedIdentity/userAssignedIdentities/MD-Blob-Identity/federatedIdentityCredentials/my-fed-cred",
  "issuer": "https://oidc.prod-aks.azure.com/3c4e99f3-4831-4352-ae86-4d8f59512865/",
  "name": "my-fed-cred",
  "resourceGroup": "test",
  "subject": "system:serviceaccount:demo:md-blob-sa",
  "systemData": null,
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials"
}

Subject format::system:serviceaccount::

5、Create a ServiceAccount in Kubernetes and deploy the application.

Create Kubernetes ServiceAccount

1
2
3
4
5
6
7
8
# blob-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: blob-access-sa
  namespace: demo
  annotations:
    azure.workload.identity/client-id: "${USER_ASSIGNED_CLIENT_ID}"

apply

kubectl apply -f blob-sa.yaml

6、Deploy Application Pod

Here we use Python as an example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# python-blob.yaml
apiVersion: v1
kind: Pod
metadata:
  name: blob-client
  namespace: demo
  labels:
    azure.workload.identity/use: "true"  # This label is required!
spec:
  serviceAccountName: blob-access-sa
  containers:
    - name: app
      image: python:3.11-slim
      command: ["sh", "-c"]
      args:
        - |
          pip install azure-identity azure-storage-blob && \
          python -c "
from azure.storage.blob import BlobServiceClient
from azure.identity import DefaultAzureCredential
import os

account = 'mdblob001'
url = f'https://mdblob001.blob.core.windows.net'
client = BlobServiceClient(account_url=url, credential=DefaultAzureCredential())
print('Containers:', [c.name for c in client.list_containers()])
"
      env:
        - name: AZURE_CLIENT_ID
          value: "${USER_ASSIGNED_CLIENT_ID}"  # Optional but recommended to explicitly specify
  restartPolicy: Never

Deploy and verify:

kubectl apply -f python-blob.yaml 
kubectl logs blob-client # The application can successfully list the Blob Storage containers, and it accesses Blob Storage using a token, achieving the entire process without any secrets.

With these three methods—Entra ID app credentials, system-assigned managed identity, and user-assigned identity with Workload Identity—you now have flexible, secure options for accessing Azure Blob Storage from AKS workloads.