π΅οΈ Replacing SAS Tokens with User Assigned Managed Identity (UAMI) in AzCopy for Blob Uploads
Using Shared Access Signature (SAS) tokens with azcopy
is common β but rotating tokens and handling them securely can be a hassle. To improve security and simplify our automation, I recently replaced SAS-based authentication in our scheduled AzCopy jobs with Azure User Assigned Managed Identity (UAMI).
In this post, Iβll walk through how to:
- Replace AzCopy SAS tokens with managed identity authentication
- Assign the right roles to the UAMI
- Use
azcopy login
to authenticate non-interactively - Automate the whole process in PowerShell
π Why Remove SAS Tokens?
SAS tokens are useful, but:
- π Theyβre still secrets β and secrets can be leaked
- π They expire β which breaks automation when not rotated
- π They grant broad access β unless scoped very carefully
Managed Identity is a much better approach when the copy job is running from within Azure (like an Azure VM or Automation account).
π Project Goal
Replace the use of SAS tokens in an AzCopy job that uploads files from a local UNC share to Azure Blob Storage β by using a User Assigned Managed Identity.
β Prerequisites
To follow along, youβll need:
- A User Assigned Managed Identity (UAMI)
- A Windows Server or Azure VM to run the copy job
- Access to a local source folder or UNC share (e.g.,
\\fileserver\\data\\export\\
) - AzCopy v10.7+ installed on the machine
- Azure RBAC permissions to assign roles
βΉοΈ Check AzCopy Version: Run
azcopy --version
to ensure you're using v10.7.0 or later, which is required for--identity-client-id
support.
π§ Step-by-Step Setup
π οΈ Step 1: Create the UAMI
β CLI
az identity create \
--name my-azcopy-uami \
--resource-group my-resource-group \
--location <region>
β Portal
- Go to Managed Identities in the Azure Portal
- Click + Create and follow the wizard
ποΈ Step 2: Assign the UAMI to the Azure VM
AzCopy running on a VM must be able to assume the identity. Assign the UAMI to your VM:
β CLI
az vm identity assign \
--name my-vm-name \
--resource-group my-resource-group \
--identities my-azcopy-uami
β Portal
- Navigate to the Virtual Machines blade
- Select the VM running your AzCopy script
- Under Settings, click Identity
- Go to the User assigned tab
- Click + Add, select your UAMI, then click Add
π Step 3: Assign RBAC Permissions to UAMI
For AzCopy to function correctly with a UAMI, the following role assignments are recommended:
- Storage Blob Data Contributor: Required for read/write blob operations
- Storage Blob Data Reader: (Optional) For read-only scenarios or validation scripts
- Reader: (Optional) For browsing or metadata-only permissions on the storage account
β³ RBAC Tip: It may take up to 5 minutes for role assignments to propagate fully. If access fails initially, wait and retry.
β CLI
az role assignment create \
--assignee <client-id-or-object-id> \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage-account>/blobServices/default/containers/<container-name>"
az role assignment create \
--assignee <client-id-or-object-id> \
--role "Storage Blob Data Reader" \
--scope "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage-account>"
az role assignment create \
--assignee <client-id-or-object-id> \
--role "Reader" \
--scope "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage-account>"
β Portal
- Go to your Storage Account in the Azure Portal
- Click on the relevant container (or stay at the account level for broader scope)
- Open Access Control (IAM)
- Click + Add role assignment
- Repeat this for each role:
- Select Storage Blob Data Contributor, assign to your UAMI, and click Save
- Select Storage Blob Data Reader, assign to your UAMI, and click Save
- Select Reader, assign to your UAMI, and click Save
π§ͺ Step 4: Test AzCopy Login Using UAMI
$clientId = "<your-uami-client-id>"
& "C:\azcopy\azcopy.exe" login --identity --identity-client-id $clientId
You should see a confirmation message that AzCopy has successfully logged in.
π To verify AzCopy is authenticated with the correct identity, you can run:
This will show the login type and confirm whether the token is being sourced from the Managed Identity.
π Step 5: Upload Files Using AzCopy + UAMI
Here's the PowerShell script that copies all files from a local share to the Blob container:
$clientId = "<your-uami-client-id>"
# Login with Managed Identity
& "C:\azcopy\azcopy.exe" login --identity --identity-client-id $clientId
# Run the copy job
& "C:\azcopy\azcopy.exe" copy \
"\\\\fileserver\\data\\export\\" \
"https://<your-storage-account>.blob.core.windows.net/<container-name>" \
--overwrite=true \
--from-to=LocalBlob \
--blob-type=Detect \
--put-md5 \
--recursive \
--log-level=INFO
π‘ UNC Note: Double backslashes are used in PowerShell to represent UNC paths properly.
This script can be scheduled using Task Scheduler or run on demand.
β±οΈ Automate with Task Scheduler (Optional)
To automate the job:
- Open Task Scheduler on your VM
- Create a New Task (not a Basic Task)
- Under General, select "Run whether user is logged on or not"
- Under Actions, add a new action to run
powershell.exe
- Set the arguments to point to your
.ps1
script - Ensure the AzCopy path is hardcoded in your script
π Troubleshooting Common Errors
β 403 AuthorizationPermissionMismatch
- Usually means the identity doesnβt have the correct role or the role hasnβt propagated yet
- Double-check:
- UAMI is assigned to the VM
- UAMI has
Storage Blob Data Contributor
on the correct container - Wait 2β5 minutes and try again
β azcopy : The term 'azcopy' is not recognized
- AzCopy is not in the system PATH
- Solution: Use the full path to
azcopy.exe
, likeC:\azcopy\azcopy.exe
π‘οΈ Benefits of Switching to UAMI
- β No secrets or keys stored on disk
- β No manual token expiry issues
- β Access controlled via Azure RBAC
- β Easily scoped and auditable
π§Ό Final Thoughts
Replacing AzCopy SAS tokens with UAMI is one of those small wins that pays dividends over time. Once set up, it's secure, robust, and hands-off.
Let me know if you'd like a variant of this that works from Azure Automation or a hybrid worker!