Search code examples
azurepowershell

PowerShell script to list Azure storage blobs


I have this requirement to get storage account details and list storage blobs filtered out by specific container "test". I got this reference code from stackoverflow which will output the container based on tag value. I tried adding the "if" condition to the same script to filter container details which isn't giving any results, also unsure how to list blobs in the same script filtered by container "test".

I'm expecting the script to output storage account details (filtered by tags), storage account size, container(filtered by specific container) and list blobs from the filtered containers.

Request for more details if the above isn't enough.

Connect-AzAccount -Tenant 'xxxxx' -UseDeviceAuthentication
# Get all subscriptions
$subscriptions = Get-AzSubscription

# Define the tag key to filter by
$tagKey = "any"

# Initialize an array to store the results
$results = @()

foreach ($subscription in $subscriptions) {
    # Set the current subscription context
    Set-AzContext -SubscriptionId $subscription.Id

    # Get all storage accounts in the current subscription
    $storageAccounts = Get-AzStorageAccount | Where-Object { $_.Tags.ContainsKey($tagKey) }

    foreach ($storageAccount in $storageAccounts) {
        # Get the metrics for the storage account
        $resourceId = "/subscriptions/$($subscription.Id)/resourceGroups/$($storageAccount.ResourceGroupName)/providers/Microsoft.Storage/storageAccounts/$($storageAccount.StorageAccountName)"
        $uri = "https://management.azure.com$resourceId/providers/Microsoft.Insights/metrics?api-version=2023-10-01&metricnames=UsedCapacity&aggregation=Average"

        try {
            $response = Invoke-AzRestMethod -Method Get -Uri $uri
            $metrics = $response.Content | ConvertFrom-Json
            $usedCapacityMetric = $metrics.value | Where-Object { $_.name.value -eq "UsedCapacity" }

            if ($usedCapacityMetric) {
                $averageCapacity = $usedCapacityMetric.timeseries.data.average | Measure-Object -Sum | Select-Object -ExpandProperty Sum
            } else {
                $averageCapacity = 0
            }
        } catch {
            Write-Warning "Failed to retrieve metrics for storage account: $($storageAccount.StorageAccountName)"
            $averageCapacity = 0
        }

        $ctx = $storageAccount.Context
        $containers = Get-AzStorageContainer -Context $ctx

        foreach ($container in $containers) {
            if ($container.Name -eq "test") {
        $results += [PSCustomObject]@{
            #SubscriptionId       = $subscription.Id
            SubscriptionName     = $subscription.Name
            ResourceGroup        = $storageAccount.ResourceGroupName
            StorageAccount       = $storageAccount.StorageAccountName
            ContainerName        = $container.Name
            UsedCapacityInBytes  = $averageCapacity
            TagName              = $tagKey
            TagValue             = $storageAccount.Tags[$tagKey]
        }
      }
    }
}
}

# Output the results
$results | Format-Table -AutoSize

Solution

  • I'm expecting the script to output storage account details (filtered by tags), storage account size, container(filtered by specific container) and list blobs from the filtered containers.

    You can use the below script to get the storage account details (filtered by tags), storage account size, container(filtered by specific container) and list blobs from the filtered containers.

    Script:

    Connect-AzAccount -Tenant 'xxxxx' -UseDeviceAuthentication
    # Get all subscriptions
    $subscriptions = Get-AzSubscription
    
    # Define the tag key to filter by
    $tagKey = "createdby"
    
    # Initialize an array to store the results
    $results = @()
    
    foreach ($subscription in $subscriptions) {
        # Set the current subscription context
        Set-AzContext -SubscriptionId $subscription.Id
    
        # Get all storage accounts in the current subscription
        $storageAccounts = Get-AzStorageAccount | Where-Object { $_.Tags.ContainsKey($tagKey) }
    
        foreach ($storageAccount in $storageAccounts) {
            # Get the metrics for the storage account
            $resourceId = "/subscriptions/$($subscription.Id)/resourceGroups/$($storageAccount.ResourceGroupName)/providers/Microsoft.Storage/storageAccounts/$($storageAccount.StorageAccountName)"
            $uri = "https://management.azure.com$resourceId/providers/Microsoft.Insights/metrics?api-version=2023-10-01&metricnames=UsedCapacity&aggregation=Average"
    
            try {
                $response = Invoke-AzRestMethod -Method Get -Uri $uri
                $metrics = $response.Content | ConvertFrom-Json
                $usedCapacityMetric = $metrics.value | Where-Object { $_.name.value -eq "UsedCapacity" }
    
                if ($usedCapacityMetric) {
                    $averageCapacity = $usedCapacityMetric.timeseries.data.average | Measure-Object -Sum | Select-Object -ExpandProperty Sum
                } else {
                    $averageCapacity = 0
                }
            } catch {
                Write-Warning "Failed to retrieve metrics for storage account: $($storageAccount.StorageAccountName)"
                $averageCapacity = 0
            }
    
            $ctx = $storageAccount.Context
            $containers = Get-AzStorageContainer -Context $ctx | Where-Object { $_.Name -eq "test" }
    
            foreach ($container in $containers) {
              $blobs = Get-AzStorageBlob -Container $container.Name -Context $ctx
              $results += [PSCustomObject]@{
                #SubscriptionId       = $subscription.Id
                SubscriptionName     = $subscription.Name
                ResourceGroup        = $storageAccount.ResourceGroupName
                StorageAccount       = $storageAccount.StorageAccountName
                ContainerName        = $container.Name
                UsedCapacityInBytes  = $averageCapacity
                TagName              = $tagKey
                TagValue             = $storageAccount.Tags[$tagKey]
                Blobs                = $blobs.Name -join ", "
            }
          }
        }
    }
    
    
    # Output the results
    $results | Format-Table -AutoSize
    

    Output:

    SubscriptionName                      ResourceGroup StorageAccount ContainerName UsedCapacityInBytes TagName   TagValue Blobs                                                           
    ----------------                      ------------- -------------- ------------- ------------------- -------   -------- -----                                                           
    xxxxx xxxxxx xxxxxxxxxxx Subscription venkatesan-rg venkat891      test                     17840077 createdby venkat   22-07-2024.html, 24-07-2024.html, 26-07-2024.html, earth.mp4
    xxxxx xxxxxx xxxxxxxxxxx Subscription venkatesan-rg venkat789      test                     89083079 createdby venkat   test.mp4, research.html, data.html, sun.mp4, 001.csv 
    

    Update:

    You can use the below modify code to get the virtual directory only from the storage account.

            foreach ($container in $containers) {
              $blobs = Get-AzStorageBlob -Container $container.Name -Context $ctx
              $directories = $blobs | ForEach-Object {
                    $parts = $_.Name.Split('/')
                    for ($i = 0; $i -lt $parts.Length - 1; $i++) {
                        $parts[0..$i] -join '/'
                    }
                } | Sort-Object -Unique
    
              $results += [PSCustomObject]@{
                #SubscriptionId       = $subscription.Id
                SubscriptionName     = $subscription.Name
                ResourceGroup        = $storageAccount.ResourceGroupName
                StorageAccount       = $storageAccount.StorageAccountName
                ContainerName        = $container.Name
                UsedCapacityInBytes  = $averageCapacity
                TagName              = $tagKey
                TagValue             = $storageAccount.Tags[$tagKey]
                Directories          = $directories -join ", "
               
            }