StorageAccountBlobHelper.psm1
$script:AccessToken = $null $script:AccessTokenExpiry = $null $script:ClientId = $null function Invoke-WithRetry { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateSet('GET', 'PUT', 'POST', 'DELETE')] [string]$Method, [Parameter(Mandatory)] [string]$Uri, [Parameter(Mandatory)] [hashtable]$Headers, [Parameter(Mandatory = $false)] $Body, [Parameter(Mandatory = $false)] [string]$OutFile ) $maxRetries = 5 $retryDelaySeconds = 2 for ($i = 0; $i -lt $maxRetries; $i++) { try { if ($OutFile) { return Invoke-WebRequest -Uri $Uri -Method $Method -Headers $Headers -OutFile $OutFile -Body $Body -ErrorAction Stop } else { return Invoke-RestMethod -Uri $Uri -Method $Method -Headers $Headers -Body $Body -ErrorAction Stop } } catch { if ($_.Exception.Response.StatusCode.Value__ -in 429, 500, 502, 503, 504) { Write-Host "Request failed with status $($_.Exception.Response.StatusCode.Value__). Retrying in $retryDelaySeconds seconds..." -ForegroundColor Yellow Start-Sleep -Seconds $retryDelaySeconds $retryDelaySeconds *= 2 } else { throw } } } throw "Request failed after $maxRetries attempts." } function Set-StorageManagedIdentity { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$ClientId ) $script:ClientId = $ClientId Write-Verbose "Using Managed Identity ClientId: $ClientId" } function Get-ClientId { return $script:ClientId } function Set-AccessToken { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$AccessToken, [Parameter(Mandatory = $false)] [string]$AccessTokenExpiry ) $script:AccessToken = $AccessToken $script:AccessTokenExpiry = $AccessTokenExpiry Write-Verbose "Using AccessToken: $script:AccessToken" Write-Verbose "Using AccessTokenExpiry: $script:AccessTokenExpiry" } function Get-AccessToken { $resource = "https://storage.azure.com/" if (-not $script:AccessToken -or (Get-Date) -ge $script:AccessTokenExpiry) { $metadataUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=$resource" if ($script:ClientId) { $metadataUri += "&client_id=$($script:ClientId)" } $tokenResponse = Invoke-WithRetry -Uri $metadataUri ` -Method GET ` -Headers @{Metadata="true"} ` -ErrorAction Stop $script:AccessToken = $tokenResponse.access_token $script:AccessTokenExpiry = (Get-Date).AddSeconds($tokenResponse.expires_in - 60) } return $script:AccessToken } function New-Blob { [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$StorageAccountName, [Parameter(Mandatory)] [string]$ContainerName, [Parameter(Mandatory)] [string]$BlobName, [Parameter(Mandatory)] [string]$FilePath ) $token = Get-AccessToken $url = "https://$StorageAccountName.blob.core.windows.net/$ContainerName/$BlobName" $fileBytes = [System.IO.File]::ReadAllBytes($FilePath) return Invoke-WithRetry -Uri $url -Method PUT -Headers @{ Authorization = "Bearer $token" "x-ms-blob-type" = "BlockBlob" "x-ms-version" = "2021-10-04" } -Body $fileBytes } function Get-Blob { [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$StorageAccountName, [Parameter(Mandatory)] [string]$ContainerName, [Parameter(Mandatory)] [string]$BlobName, [Parameter(Mandatory)] [string]$DownloadPath ) $token = Get-AccessToken $url = "https://$StorageAccountName.blob.core.windows.net/$ContainerName/$BlobName" return Invoke-WithRetry -Uri $url ` -Method GET ` -Headers @{ Authorization = "Bearer $token" "x-ms-version" = "2021-10-04" } ` -OutFile $DownloadPath ` -ErrorAction Stop } function Remove-Blob { [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$StorageAccountName, [Parameter(Mandatory)] [string]$ContainerName, [Parameter(Mandatory)] [string]$BlobName ) $token = Get-AccessToken $url = "https://$StorageAccountName.blob.core.windows.net/$ContainerName/$BlobName" return Invoke-WithRetry -Uri $url ` -Method DELETE ` -Headers @{ Authorization = "Bearer $token" "x-ms-version" = "2021-10-04" } ` -ErrorAction Stop } Export-ModuleMember -Function Set-StorageManagedIdentity, Get-ClientId, Set-AccessToken, Get-AccessToken, New-Blob, Get-Blob, Remove-Blob |