Public/Get-SpecAzTableRowUsingSAS.ps1

function Get-SpecAzTableRowUsingSAS {
    <#
    .SYNOPSIS
    Retrieves data from an Azure Table Storage using a Shared Access Signature (SAS) token.
 
    .DESCRIPTION
    This function allows you to retrieve data from an Azure Table Storage using a SAS token for authentication. You can retrieve all data from the table or specify key-value pairs to filter the results.
 
    .PARAMETER SAS
    The Shared Access Signature (SAS) token for authenticating with the Azure Table Storage.
 
    .PARAMETER StorageAccount
    The name of the Azure Storage Account containing the table.
 
    .PARAMETER TableName
    The name of the Azure Table to retrieve data from.
 
    .PARAMETER Key
    (Optional) The key to use for filtering data.
 
    .PARAMETER Value
    (Optional) The value to use for filtering data.
 
    .PARAMETER CustomFilter
    (Optional) An optional custom filter to apply to the URI.
 
    .PARAMETER GetAllRows
    A switch parameter to indicate whether to retrieve all rows in the table. (All table data)
 
    .EXAMPLE
    Retrieve all data from the specified Azure Table using the -GetAllRows switch:
    Get-SpecAzTableRowUsingSAS -SAS $SasToken -StorageAccount "myaccount" -TableName "mytable" -GetAllRows
 
    .EXAMPLE
    Retrieve row data from the specified Azure Table using the -Key and -Value:
    Get-SpecAzTableRowUsingSAS -SAS $SasTokenReadToken -StorageAccount $storageAccount -TableName $tableName -Key 'DeviceType' -Value 'HR'
    Returns the row where 'DeviceType' = 'HR'
 
    .EXAMPLE
    Retrieve row data from the specified Azure Table using a custom filter:
    $customFilter = "(Last_Logged_On eq 'fred.bloggs') and (Device_Name eq 'mydevice')"
 
    try {
        Get-SpecAzTableRowUsingSAS -SAS $SasTokenReadToken -StorageAccount $storageAccount -TableName $tableName -CustomFilter $customFilter -ea stop
        write-host "Success" -foregroundcolor darkgreen
    } catch {
        write-host "An error occurred. $_" -foregroundcolor darkyellow
    }
 
    Returns the row where 'Last_Logged_On' = 'fred.bloggs' and 'Device_Name' = 'mydevice'
 
    .NOTES
    Author: owen.heaume
    Version: 1.1 - Initial release
                1.1.1 - Now throws on errors so that they can be trapped via try/catch
                1.1.2 - retrieves more than 1000 rows if present (previously would only return 1000 rows on large tables
                2.0.0 - Now uses 'Write-Error' instead of throw to enable function use elegantly within try / catch
    #>


    [cmdletbinding()]
    param(
        [parameter (mandatory = $true)]
        [string]$SasToken,

        [parameter (mandatory = $true)]
        [string]$StorageAccount,

        [parameter (mandatory = $true)]
        [string]$TableName,

        [parameter (mandatory = $false, ParameterSetName = 'KeyValue')]
        [string]$Key,

        [parameter (mandatory = $false, ParameterSetName = 'KeyValue')]
        [string]$Value,

        [parameter (mandatory = $false, ParameterSetName = 'Custom')]
        [string]$CustomFilter,

        [parameter (ParameterSetName = 'GetAllRows')]
        [Switch]$GetAllRows
    )

    begin {
        $headers = @{
            Accept = 'application/json;odata=nometadata'
        }
    }

    process {
        # Validate key and value parameters
        if ($key -and [string]::IsNullOrEmpty($value)) {
            Write-Error 'You have requested to return filtered data but the [value] parameter is missing'
        }

        if ($value -and [string]::IsNullOrEmpty($key)) {
            Write-Error 'You have requested to return filtered data but the [key] parameter is missing'
        }

        # Construct the initial URI
        if ($key -and $value) {
            Write-Verbose 'Requesting filtered data'
            $filter = "`$filter=($key eq '$value')"
            $tableUri = Get-SpecAzTableUri -SAS $SasToken -StorageAccount $StorageAccount -TableName $TableName -Key $key -Value $Value
        } elseif ($customfilter) {
            $tableUri = Get-SpecAzTableUri -SAS $SasToken -StorageAccount $StorageAccount -TableName $TableName -CustomFilter $CustomFilter
        } else {
            Write-Verbose 'Requesting all data'
            $tableUri = Get-SpecAzTableUri -SAS $SasToken -StorageAccount $StorageAccount -TableName $TableName -GetAllRows
        }

        $allItems = @()
        $nextPartitionKey = $null
        $nextRowKey = $null

        do {
            try {
                $uri = $tableUri + "&`$top=1000"
                if ($nextPartitionKey -and $nextRowKey) {
                    $uri += "&NextPartitionKey=$nextPartitionKey&NextRowKey=$nextRowKey"
                }

                Write-Verbose "Making request to URI: $uri"
                $response = Invoke-WebRequest -Method Get -Uri $uri -Headers $headers -ContentType application/json -ErrorAction Stop -UseBasicParsing

                $content = $response.Content | ConvertFrom-Json

                if ($content -and $content.value) {
                    $allItems += $content.value
                } else {
                    Write-Host 'No data returned in response' -ForegroundColor DarkYellow
                }

                Write-Verbose "Response Headers: $($response.Headers | Format-List)"

                if ($response.Headers['x-ms-continuation-NextPartitionKey'] -and $response.Headers['x-ms-continuation-NextRowKey']) {
                    $nextPartitionKey = $response.Headers['x-ms-continuation-NextPartitionKey']
                    $nextRowKey = $response.Headers['x-ms-continuation-NextRowKey']
                    Write-Verbose "Received continuation tokens: NextPartitionKey=$nextPartitionKey, NextRowKey=$nextRowKey"
                } else {
                    Write-Verbose 'No continuation headers found'
                    $nextPartitionKey = $null
                    $nextRowKey = $null
                }
            } catch [System.Net.WebException] {
                if ($_.Exception.Message -contains 'The remote server returned an error: (404) Not Found.') {
                    Write-Error "Table [$TableName] not found. Please check that the table exists and that you have not made a typo. $_"
                } elseif ($_.Exception.Message -match 'The remote name could not be resolved') {
                    Write-Error "Storage account [$StorageAccount] not found. Please check that the storage account exists and that you have not made a typo. $_"
                } else {
                    # Handle other WebExceptions
                    Write-Error "A WebException occurred: $($_.Exception.Message)"
                }
            } catch {
                Write-Error "An error occurred: $_"
            }
        } while ($nextPartitionKey -or $nextRowKey)

        return $allItems
    }
}