Skip to content

Instantly share code, notes, and snippets.

@RylandDeGregory
Last active September 29, 2025 19:30
Show Gist options
  • Select an option

  • Save RylandDeGregory/c65563d0b090fc32115be7025d1ce722 to your computer and use it in GitHub Desktop.

Select an option

Save RylandDeGregory/c65563d0b090fc32115be7025d1ce722 to your computer and use it in GitHub Desktop.
Azure Table Storage REST operations using PowerShell.
$StorageAccount = ''
$Table = ''
$PartitionKey = ''
$RowKey = ''
# Set Azure Table Storage request headers
$Date = [DateTime]::UtcNow.ToString('R')
$AzTableHeaders = @{
'Accept' = 'application/json;odata=nometadata'
'x-ms-version' = '2020-08-04'
'x-ms-date' = $Date
}
#region OAuth
# Operations require the calling Principal being assigned the
# "Storage Table Data Contributor" Azure RBAC Role on (at least) the Storage Account scope
# Connect to Azure
Connect-AzAccount
$AZStorageToken = Get-AzAccessToken -ResourceTypeName Storage
$AzTableHeaders += @{'Authorization' = "$($AzStorageToken.Type) $($AzStorageToken.Token)"}
#endregion OAuth
#region AccessKey
$AccessKey = ''
# SigningString will differ depending on the API operation being performed
$SigningString = "$Date`n/$StorageAccount/$Table(PartitionKey='$PartitionKey',RowKey='$RowKey')"
$HmacSha = [System.Security.Cryptography.HMACSHA256]@{Key = [Convert]::FromBase64String($AccessKey)}
$Signature = [Convert]::ToBase64String($HmacSha.ComputeHash([Text.Encoding]::UTF8.GetBytes($SigningString)))
$AzTableHeaders += @{'Authorization' = "SharedKeyLite $StorageAccount`:$Signature"}
#endregion AccessKey
#region Operations
# Get all Records in Table
$TableRecords = @()
$TableResponse = Invoke-WebRequest -Method Get -Uri "https://$StorageAccount.table.core.windows.net/$Table()" -Headers $AzTableHeaders
$TableRecords += $TableResponse | Select-Object -ExpandProperty Content | ConvertFrom-Json | Select-Object -ExpandProperty value
$TableRecords += while($TableResponse.Headers.'x-ms-continuation-NextPartitionKey') {
$TableResponse = Invoke-WebRequest -Method Get -Uri "https://$StorageAccount.table.core.windows.net/$Table()?NextPartitionKey=$($TableResponse.Headers.'x-ms-continuation-NextPartitionKey')&NextRowKey=$($TableResponse.Headers.'x-ms-continuation-NextRowKey')" -Headers $AzTableHeaders
$TableResponse | Select-Object -ExpandProperty Content | ConvertFrom-Json | Select-Object -ExpandProperty value
}
# Get all Records by PartitionKey
Invoke-RestMethod -Method Get -Uri "https://$StorageAccount.table.core.windows.net/$Table()?`$filter=PartitionKey eq '$PartitionKey'" -Headers $AzTableHeaders | Select-Object -ExpandProperty value
# Get Record by RowKey
Invoke-RestMethod -Method Get -Uri "https://$StorageAccount.table.core.windows.net/$Table(PartitionKey='$PartitionKey',RowKey='$RowKey')" -Headers $AzTableHeaders
# Insert Record
$InsertBody = @{
PartitionKey = $PartitionKey
RowKey = $RowKey.ToString()
} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "https://$StorageAccount.table.core.windows.net/$Table" -Body $InsertBody -Headers $AzTableHeaders -ContentType 'application/json'
# Update Record
$UpdateBody = @{
Name = 'NewName'
} | ConvertTo-Json
Invoke-RestMethod -Method Put -Uri "https://$StorageAccount.table.core.windows.net/$Table(PartitionKey='$PartitionKey',RowKey='$RowKey')" -Body $UpdateBody -Headers $AzTableHeaders -ContentType 'application/json'
# Delete Record
$DeleteHeaders = $AzTableHeaders += @{'If-Match' = '*'}
Invoke-RestMethod -Method Delete -Uri "https://$StorageAccount.table.core.windows.net/$Table(PartitionKey='$PartitionKey',RowKey='$RowKey')" -Headers $DeleteHeaders
#endregion Operations
@GreyWilk
Copy link

This and the related blog post (link) have really helped me! All the other blogs and tips I've found have used SAS keys which is lazy, old and insecure! πŸ˜† πŸ’―
Just wanted to, in some way, say thanks! This was the only way to reach out to you without paying for LinkedIn πŸ˜„

@RylandDeGregory
Copy link
Author

Hey @GreyWilk,

Thank you for the positive feedback! I’m glad you found it useful! πŸ˜„

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment