Files
NetSPI-MicroBurst/Az/Get-AzBatchAccountData.ps1
2025-03-01 08:58:23 +00:00

219 lines
11 KiB
PowerShell

<#
File: Get-AzBatchAccountData.ps1
Author: Karl Fosaaen (@kfosaaen), NetSPI - 2023
Description: PowerShell functions for dumping Azure Batch commands, environmental variables, etc.
#>
function Get-AzBatchAccountData{
<#
.SYNOPSIS
PowerShell function for dumping information from Azure Batch Accounts.
.DESCRIPTION
The function will dump available information for an Azure Batch Account. This includes environmental variables, tasks, jobs, etc.
.PARAMETER Subscription
Subscription to use.
.PARAMETER folder
The folder to output to.
.EXAMPLE
PS C:\> Get-AzBatchAccountData -folder BatchOutput -Verbose
VERBOSE: Logged In as kfosaaen@example.com
VERBOSE: Dumping Batch Accounts from the "Sample Subscription" Subscription
VERBOSE: 1 Batch Account(s) Enumerated
VERBOSE: Attempting to dump data from the testspi account
VERBOSE: Attempting to dump keys
VERBOSE: 1 Pool(s) Enumerated
VERBOSE: Attempting to dump pool data
VERBOSE: 13 Job(s) Enumerated
VERBOSE: Attempting to dump job data
VERBOSE: Completed dumping of the testspi account
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false,
HelpMessage="Subscription to use.")]
[string]$Subscription = "",
[Parameter(Mandatory=$false,
HelpMessage="Folder to output to.")]
[string]$folder = ""
)
# Check to see if we're logged in
$LoginStatus = Get-AzContext
$accountName = ($LoginStatus.Account).Id
if ($LoginStatus.Account -eq $null){Write-Warning "No active login. Prompting for login."
try {Connect-AzAccount -ErrorAction Stop}
catch{Write-Warning "Login process failed."}
}
else{}
# Subscription name is technically required if one is not already set, list sub names if one is not provided "Get-AzSubscription"
if ($Subscription){
Select-AzSubscription -SubscriptionName $Subscription | Out-Null
}
else{
# List subscriptions, pipe out to gridview selection
$Subscriptions = Get-AzSubscription -WarningAction SilentlyContinue
$subChoice = $Subscriptions | Out-GridView -Title "Select One or More Subscriptions" -PassThru
foreach ($sub in $subChoice) {Get-AzBatchAccountData -Subscription $sub -folder $folder}
return
}
Write-Verbose "Logged In as $accountName"
# Check Folder Path
if ($folder -ne ""){
if(Test-Path $folder){}
else{New-Item -ItemType Directory $folder | Out-Null}
}
else{$folder = $PWD.Path}
# Stop the change warnings
Update-AzConfig -DisplayBreakingChangeWarning $false | Out-Null
Write-Verbose "Dumping Batch Accounts from the `"$((get-azcontext).Subscription.Name)`" Subscription"
#Get list of Batch Accounts
$batchAccounts = Get-AzBatchAccount
Write-Verbose "`t$($batchAccounts.Count) Batch Account(s) Enumerated"
$batchAccounts | ForEach-Object{
$currentBatchAccount = $_.AccountName
Write-Verbose "`t`tAttempting to dump data from the $currentBatchAccount account"
# Get Account Keys
Try{
Write-Verbose "`t`t`tAttempting to dump keys"
$batchKeys = Get-AzBatchAccountKeys -AccountName $_.AccountName
"Primary Key: "+$batchKeys.PrimaryAccountKey | Out-File -Append "$folder\$currentBatchAccount-Keys.txt"
"Secondary Key: "+$batchKeys.SecondaryAccountKey | Out-File -Append "$folder\$currentBatchAccount-Keys.txt"
}
Catch{Write-Verbose "`t`t`tNo ListKeys Permissions on the $currentBatchAccount Batch Account"}
# Get Batch Context
$batchContext = Get-AzBatchAccount -AccountName $_.AccountName
# Get Batch Pools
$batchPools = Get-AzBatchPool -BatchContext $batchContext -Verbose:$false
Write-Verbose "`t`t`t$($batchPools.Count) Pool(s) Enumerated"
Write-Verbose "`t`t`t`tAttempting to dump pool data"
# For Each Pool, get the ENV variables and commands from the start task
$batchPools | ForEach-Object {
"Pool: "+$_.Id | Out-File -Append "$folder\$currentBatchAccount-Pools.txt"
"Start Task Command: "+$_.StartTask.CommandLine | Out-File -Append "$folder\$currentBatchAccount-Pools.txt"
if($_.StartTask.EnvironmentSettings.Values -ne $null){
"Start Task ENV: "| Out-File -Append "$folder\$currentBatchAccount-Pools.txt"
$tempKey = $_.StartTask.EnvironmentSettings
$_.StartTask.EnvironmentSettings.keys | ForEach-Object{"`t"+$_+"="+$tempKey.$_ | Out-File -Append "$folder\$currentBatchAccount-Pools.txt"}
}
if($_.StartTask.ResourceFiles.StorageContainerUrl -ne $null){
"Start Task Files: "+$_.StartTask.ResourceFiles.StorageContainerUrl+"`n`n" | Out-File -Append "$folder\$currentBatchAccount-Pools.txt"
}
}
# Get list of Jobs
$batchJobs = Get-AzBatchJob -BatchContext $batchContext -Verbose:$false
Write-Verbose "`t`t`t$($batchJobs.Count) Job(s) Enumerated"
Write-Verbose "`t`t`t`tAttempting to dump job data"
# For Each Job, get the ENV variables and commands from the tasks
$batchJobs | ForEach-Object {
# Job Manager
"==================== Job ID: "+$_.Id+" ====================" | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
"Job Manager Task Command: "+$_.JobManagerTask.CommandLine | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
if($_.JobManagerTask.EnvironmentSettings.Values -ne $null){
"Job Manager ENV: "| Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
$tempKeyJM = $_.JobManagerTask.EnvironmentSettings
$_.JobManagerTask.EnvironmentSettings.keys | ForEach-Object{"`t"+$_+"="+$tempKeyJM.$_ | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"}
}
if($_.JobManagerTask.ResourceFiles.StorageContainerUrl -ne $null){
"Job Manager Task Files: "+$_.JobManagerTask.ResourceFiles.StorageContainerUrl+"`n" | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
# Job Prep
"Job Preparation Task Command: "+$_.JobPreparationTask.CommandLine | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
if($_.JobPreparationTask.EnvironmentSettings.Values -ne $null){
"Job Preparation ENV: "| Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
$tempKeyJP = $_.JobPreparationTask.EnvironmentSettings
$_.JobPreparationTask.EnvironmentSettings.keys | ForEach-Object{"`t"+$_+"="+$tempKeyJP.$_ | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"}
}
if($_.JobPreparationTask.ResourceFiles.StorageContainerUrl -ne $null){
"Job Preparation Task Files: "+$_.JobPreparationTask.ResourceFiles.StorageContainerUrl+"`n" | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
# Job Release
"Job Release Task Command: "+$_.JobReleaseTask.CommandLine | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
if($_.JobReleaseTask.EnvironmentSettings.Values -ne $null){
"Job Release ENV: "| Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
$tempKeyJR = $_.JobReleaseTask.EnvironmentSettings
$_.JobReleaseTask.EnvironmentSettings.keys | ForEach-Object{"`t"+$_+"="+$tempKeyJR.$_ | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"}
}
if($_.JobReleaseTask.ResourceFiles.StorageContainerUrl -ne $null){
"Job Release Task Files: "+$_.JobReleaseTask.ResourceFiles.StorageContainerUrl+"`n" | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
# Get advanced ENV Settings
if($_.CommonEnvironmentSettings.Values -ne $null){
"Common ENV Settings: "| Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
$tempKeyENV = $_.CommonEnvironmentSettings
$_.CommonEnvironmentSettings.keys | ForEach-Object{"`t"+$_+"="+$tempKeyENV.$_ | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"}
}
# Extra line to break up jobs
"`n"| Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
# Get all the extra Sub-Tasks
$AccessToken = Get-AzAccessToken -ResourceUrl "https://batch.core.windows.net/"
if ($AccessToken.Token -is [System.Security.SecureString]) {
$ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($AccessToken.Token)
try {
$batchToken = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)
} finally {
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)
}
} else {
$batchToken = $AccessToken.Token
}
$jobsList = ((Invoke-WebRequest -Verbose:$false -Uri "https://$($batchContext.AccountEndpoint)/jobs?api-version=2022-10-01.16.0&maxresults=1000&paginationeffort=1" -Headers @{Authorization="Bearer $batchToken"}).Content | ConvertFrom-Json).value
$jobsList | ForEach-Object{
$currentJob = $_.id
# List Job-sub-tasks
$subTasks = ((Invoke-WebRequest -Verbose:$false -Uri "$($_.url)/tasks?api-version=2022-10-01.16.0&maxresults=1000&%24select=id%2Curl" -Headers @{Authorization="Bearer $batchToken"}).Content | ConvertFrom-Json).value
$subTasks | ForEach-Object{
$jobRuns = (Invoke-WebRequest -Verbose:$false -Uri "$($_.url)?api-version=2022-10-01.16.0" -Headers @{Authorization="Bearer $batchToken"}).Content | ConvertFrom-Json
$jobRuns | ForEach-Object{
"==================== Job ID: $currentJob === Sub-Task ID: $($_.id) ====================" | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
"Sub-Task Command: "+$_.commandLine | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
if($_.environmentSettings -ne "{}"){
"Sub-Task ENV: " | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
"`t"+$_.environmentSettings.name+"="+$_.environmentSettings.value | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
if($_.resourceFiles -ne $null){
"Sub-Task Files: "+($_.resourceFiles).storageContainerUrl+"`n" | Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
"`n"| Out-File -Append "$folder\$currentBatchAccount-Jobs.txt"
}
}
}
Write-Verbose "`t`tCompleted dumping of the $currentBatchAccount account"
}
}