forked from NetSPI/MicroBurst
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGet-AzKeyVaultSecretsREST.ps1
130 lines (100 loc) · 6.51 KB
/
Get-AzKeyVaultSecretsREST.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Function Get-AzKeyVaultSecretsREST
{
# Author: Karl Fosaaen (@kfosaaen), NetSPI - 2020
# Description: PowerShell function for enumerating available Key Vault Secrets using Azure Bearer tokens and the REST APIs.
# Pipe to "Export-Csv -NoTypeInformation" for easier exporting
# Use the SubscriptionId and token parameters to specify bearer tokens and subscriptions, handy for compromised bearer tokens from other services (CloudShell/AutomationAccounts/AppServices)
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false,
HelpMessage="Subscription ID")]
[string]$SubscriptionId,
[Parameter(Mandatory=$true,
HelpMessage="The management scoped token")]
[string]$managementToken,
[Parameter(Mandatory=$true,
HelpMessage="The KeyVault Scoped Token")]
[string]$vaultToken
)
# Sort out which subscription to list keys from
if ($SubscriptionId -eq ''){
# List all subscriptions for a tenant
$subscriptions = ((Invoke-WebRequest -Uri ('https://management.azure.com/subscriptions?api-version=2019-11-01') -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).content | ConvertFrom-Json).value
# Select which subscriptions to dump info for
$subChoice = $subscriptions | out-gridview -Title "Select One or More Subscriptions" -PassThru
if($subChoice.count -eq 0){Write-Verbose 'No subscriptions selected, exiting'; break}
}
else{$subChoice = $SubscriptionId; $noLoop = 1}
# Create data table to house results
$TempTbl = New-Object System.Data.DataTable
$TempTbl.Columns.Add("SubscriptionName") | Out-Null
$TempTbl.Columns.Add("KeyVault") | Out-Null
$TempTbl.Columns.Add("SecretURL") | Out-Null
$TempTbl.Columns.Add("SecretType") | Out-Null
$TempTbl.Columns.Add("SecretValue") | Out-Null
# Iterate through each subscription and list keys
foreach($sub in $subChoice){
# If subs are chosen from a list, grab the Id
if($noLoop){}
else{$SubscriptionId = $sub.subscriptionId}
if($sub.displayName -ne $null){$subName = $sub.displayName; Write-Verbose "Gathering Key Vaults for the $subName subscription"}
else{
try {$subName = ((Invoke-WebRequest -Uri (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,'?api-version=2019-11-01')) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).Content | ConvertFrom-Json).displayName}
catch{$subName = "undetermined"}
Write-Verbose "Gathering storage accounts for the $subName subscription"
}
# Get List of Key Vaults
$responseKeys = ((Invoke-WebRequest -Uri (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.KeyVault/vaults?api-version=2019-09-01")) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).Content | ConvertFrom-Json)
# Keeping the second method of vault enumeration as a backup option
try{$keycanary = $responseKeys.value | ConvertFrom-Json -ErrorAction Stop}
catch{$keycanary = $null}
if($null -eq $keycanary){
$responseKeys = ((Invoke-WebRequest -Uri (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/resources?`$filter=resourceType eq 'Microsoft.KeyVault/vaults'&api-version=2019-09-01")) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).Content | ConvertFrom-Json)
if ($responseKeys.value -ne $null){$keyVaults = $responseKeys.value}
else{$keyVaults = $null}
}
# Adjust for multiple vaults
if ($responseKeys.nextLink -ne $null){
while($responseKeys.nextLink){
$keyVaults += $responseKeys.Value
$responseKeys = ((Invoke-WebRequest -Uri $responseKeys.nextLink -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).Content | ConvertFrom-Json)
}
}
else{}
if($keyVaults -eq $null){Write-Verbose "`tNo Key Vaults enumerated for the $subName Subscription"}
else{
# Iterate through each available vault
foreach ($vault in $keyVaults){
$vaultName = $vault.name
# Get Secrets
try{
Write-Verbose "`tGetting Secrets for $vaultName"
#Instantiate running list that we can add to
$secretsListAll = @()
$secretsList = ((Invoke-WebRequest -Uri (-join ('https://',$vault.name,'.vault.azure.net/secrets?api-version=7.0')) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $vaultToken"} -UseBasicParsing).content | ConvertFrom-Json)
$secretsListAll += $secretsList.value
$nextSecrets = $secretsList.nextLink
#If there are more secrets, loop until we exhaust the vault
while($nextSecrets -ne $null)
{
$getNext = ((Invoke-WebRequest -Uri $nextSecrets -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $vaultToken"} -UseBasicParsing).Content | ConvertFrom-Json)
$nextSecrets = $getNext.nextLink
$secretsListAll += $getNext.value
}
# Get Values for each Secret
$secretsListAll | ForEach-Object{
$secretType = $_.contentType
if($secretType -eq $null){$secretType = "No_Type_Set"}
Write-Verbose "`t`tGetting a $secretType from $vaultName"
$secretValue = ((Invoke-WebRequest -Uri (-join ($_.id,'?api-version=7.0')) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $vaultToken"} -UseBasicParsing).content | ConvertFrom-Json)
# Add the key to the table
$TempTbl.Rows.Add($subName, $vaultName, $secretValue.id, $secretType, $secretValue.value) | Out-Null
}
}
catch{Write-Verbose "`t`tCurrent token does not have secrets list permissions for this vault or secret"}
}
}
$responseKeys = $null
}
Write-Output $TempTbl
}