mirror of
https://github.com/NetSPI/MicroBurst
synced 2026-06-08 12:01:29 +00:00
385 lines
23 KiB
PowerShell
385 lines
23 KiB
PowerShell
#Offload nextLink parsing to a separate function to avoid bloat
|
|
Function Get-RESTReq {
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory=$true,
|
|
HelpMessage="The management scoped token")]
|
|
[string]$managementToken,
|
|
[Parameter(Mandatory=$true)]
|
|
[string]$resourceURI
|
|
)
|
|
|
|
$runningList = @()
|
|
|
|
$list = ((Invoke-WebRequest -Uri $resourceURI -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).content | ConvertFrom-Json)
|
|
|
|
$runningList += $list.value
|
|
|
|
$nextKeys = $list.nextLink
|
|
|
|
#If we have a nextKeys param, loop until we exhaust it
|
|
while($nextKeys -ne $null){
|
|
$getNext = ((Invoke-WebRequest -Uri $nextKeys -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).Content | ConvertFrom-Json)
|
|
$nextKeys = $getNext.nextLink
|
|
$list += $getNext.value
|
|
}
|
|
|
|
$runningList
|
|
}
|
|
|
|
Function Get-AzDomainInfoREST {
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory=$false,
|
|
HelpMessage="Subscription ID")]
|
|
[string]$SubscriptionId,
|
|
|
|
[Parameter(Mandatory=$false,
|
|
HelpMessage="The management scoped token")]
|
|
[string]$managementToken,
|
|
[parameter(Mandatory=$false,
|
|
HelpMessage="Dump list of Storage Accounts.")]
|
|
[ValidateSet("Y","N")]
|
|
[String]$StorageAccounts = "Y",
|
|
|
|
[parameter(Mandatory=$false,
|
|
HelpMessage="Dump list of Resources.")]
|
|
[ValidateSet("Y","N")]
|
|
[String]$Resources = "Y",
|
|
|
|
[parameter(Mandatory=$false,
|
|
HelpMessage="Dump list of Virtual Machines.")]
|
|
[ValidateSet("Y","N")]
|
|
[String]$VMs = "Y",
|
|
|
|
[parameter(Mandatory=$false,
|
|
HelpMessage="Dump list of Network Information.")]
|
|
[ValidateSet("Y","N")]
|
|
[String]$NetworkInfo = "Y",
|
|
|
|
[parameter(Mandatory=$false,
|
|
HelpMessage="Dump list of RBAC Users/Roles/etc.")]
|
|
[ValidateSet("Y","N")]
|
|
[String]$RBAC = "Y"
|
|
|
|
)
|
|
|
|
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}
|
|
$SubscriptionId = $subChoice.subscriptionId
|
|
|
|
}
|
|
else{$subChoice = $SubscriptionId; $noLoop = 1}
|
|
|
|
Write-Verbose "Dumping information for subscription $SubscriptionID"
|
|
|
|
# Folder Parameter Checking - Creates Az folder to separate from MSOL folder
|
|
if ($folder){
|
|
if(Test-Path $folder){
|
|
if(Test-Path $folder"\Az"){}
|
|
else{New-Item -ItemType Directory $folder"\Az"|Out-Null}}
|
|
else{New-Item -ItemType Directory $folder|Out-Null ; New-Item -ItemType Directory $folder"\Az"|Out-Null}; $folder = -join ($folder, "\Az")}
|
|
else{if(Test-Path Az){}else{New-Item -ItemType Directory Az|Out-Null};$folder= -join ($pwd, "\Az")}
|
|
|
|
$resourceGroups = ((Invoke-WebRequest -uri (-join ("https://management.azure.com/subscriptions/",$SubscriptionId,"/resourcegroups?api-version=2020-10-01") ) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).content | ConvertFrom-Json).value
|
|
|
|
$subName = $subChoice.displayName
|
|
|
|
|
|
#Quirk here: not sure if it's possible to enumerate files via REST
|
|
if($StorageAccounts -eq "Y"){
|
|
|
|
#Get list of storage accounts
|
|
Write-Verbose "Getting Storage Accounts..."
|
|
|
|
$storageACCTs = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,'/providers/Microsoft.Storage/storageAccounts?api-version=2019-06-01'))
|
|
|
|
|
|
# Check Output Path
|
|
if(Test-Path $folder"\Files"){}
|
|
else{New-Item -ItemType Directory $folder"\Files" | Out-Null}
|
|
|
|
foreach($account in $storageACCTs){
|
|
|
|
#Check output path
|
|
if(Test-Path $folder"\Files\"$strgName){}
|
|
else{New-Item -ItemType Directory $folder"\Files\"$strgName | Out-Null}
|
|
|
|
$strgName = $account.name
|
|
|
|
Write-Verbose "`tGetting containers for $strgName storage account"
|
|
|
|
#Get list of containers and iterate through them
|
|
$containers = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com", $account.id,"/blobservices/default/containers?api-version=2021-01-01"))
|
|
foreach($container in $containers){
|
|
$pathName = "\Files\"+$strgName+"\Blob_Files_"+$container.Name
|
|
|
|
#Check if the container is public and write it to a file
|
|
if($container.properties.publicAccess -eq "Container"){
|
|
$containerName = $container.name
|
|
$blobUrl = (-join ("https://$strgName.blob.core.windows.net/$containerName/"))
|
|
Write-Verbose "`t`t$containerName container is Public"
|
|
$blobUrl >> $folder"\Files\ContainersFileUrls.txt"
|
|
}
|
|
}
|
|
|
|
#Enumerate through other storage resources
|
|
$shares = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com", $account.id,"/fileServices/default/shares?api-version=2021-01-01"))
|
|
foreach($share in $shares){
|
|
#Write-Output (-join ("Storage account ",$strgName, " has share ", $share.name))
|
|
}
|
|
$tables = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com", $account.id,"/tableServices/default/tables?api-version=2021-01-01"))
|
|
foreach($table in $tables){
|
|
#Write-Output (-join ("Storage account ", $strgName, " has share ", $table.name))
|
|
}
|
|
$queues = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com", $account.id,"/queueServices/default/queues?api-version=2021-01-01"))
|
|
foreach($queue in $queues){
|
|
#Write-Output (-join ("Storage account ", $strgName, " has queue ", $queue.name))
|
|
}
|
|
}
|
|
$storageCount = $StorageACCTs.count
|
|
Write-Verbose "`t$storageCount storage accounts were found."
|
|
}
|
|
|
|
|
|
if($Resources -eq "Y"){
|
|
|
|
if(Test-Path $folder"\Resources"){}
|
|
else{New-Item -ItemType Directory $folder"\Resources\" | Out-Null}
|
|
|
|
Write-Verbose "Getting AzureSQL Resources..."
|
|
|
|
$sqlServers = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.Sql/servers?api-version=2020-08-01-preview"))
|
|
Write-Output $sqlServers
|
|
$count = $sqlServers.count
|
|
Write-Verbose "`t$azureSQLServersCount AzureSQL servers were enumerated."
|
|
#Need to loop back to this since I don't have any spun up on my infra
|
|
#foreach($server in $sqlServers){
|
|
# $databases = (((Invoke-WebRequest -Uri (-join ('https://management.azure.com',$server.id,'/databases?api-version=2020-08-01-preview')) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).Content) | ConvertFrom-Json).value
|
|
#}
|
|
|
|
|
|
Write-Verbose "Getting Azure App Services..."
|
|
$appServices = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com/subscriptions/",$SubscriptionId,"/providers/Microsoft.Web/sites?api-version=2019-08-01"))
|
|
foreach($app in $appServices){
|
|
$app.properties | select State,@{name="HostNames";expression={$_.HostNames}},RepositorySiteName,UsageState,Enabled,@{name="EnabledHostNames";expression={$_.EnabledHostNames}},AvailabilityState,@{name="HostNameSslStates";expression={$_.hostNameSslStates}},ServerFarmId,Reserved,LastModifiedTimeUtc,SiteConfig,TrafficManagerHostNames,ScmSiteAlsoStopped,targetSwapSlot,hostingEnvironmentProfile,ClientAffinityEnabled,ClientCertEnabled,HostNamesDisabled,OutboundIpAddresses,PossibleOutboundIpAddresses,ContainerSize,DailyMemoryTimeQuota,SuspendedTill,MaxNumberOfWorkers,CloningInfo,SnapshotInfo,ResourceGroup,IsDefaultContainer,DefaultHostName,SlotSwapStatus,HttpsOnly,Identity,@{name="ID";expression={$app.id}},@{name="Name";expression={$app.name}},@{name="Kind";expression={$app.kind}},@{name="Location";expression={$app.location}},@{name="Type";expression={$app.type}},@{name="Tags";expression={$app.tags}} | Export-Csv -NoTypeInformation -LiteralPath $folder"\Resources\AppServices.CSV"
|
|
}
|
|
$count = $appServices.count
|
|
Write-Verbose "`t$count App Services enumerated"
|
|
|
|
|
|
Write-Verbose "Getting Azure Disks..."
|
|
$disks = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com/subscriptions/",$SubscriptionId,"/providers/Microsoft.Compute/disks?api-version=2020-12-01"))
|
|
$disks | Export-CSV -NoTypeInformation -LiteralPath $folder"\Resources\Disks.CSV"
|
|
$disks | ForEach-Object{if($_.properties.encryption -eq ""){$_.Name | Out-File -LiteralPath $folder"\Resources\Disks-NoEncryption.txt"}}
|
|
|
|
$diskDT = New-Object System.Data.DataTable("disks")
|
|
$columns = @("ResourceGroupName", "TimeCreated", "OsType", "DiskSizeGB", "DiskSizeBytes", "UniqueId", "ProvisioningState", "DiskIOPSReadWrite", "DiskMBpsReadWrite", "DiskState", "Id", "Name", "Location", "Encryption")
|
|
foreach($col in $columns){$diskDT.Columns.Add($col) | Out-Null}
|
|
foreach($disk in $disks){
|
|
|
|
$diskProps = $disk.properties
|
|
$diskDT.Rows.Add($disk.name, $diskProps.timeCreated, $diskProps.osType, $diskProps.diskSizeGB, $diskProps.diskSizeBytes, $diskProps.uniqueId, $diskProps.provisioningState, $diskProps.diskIOPSReadWrite, $diskProps.diskMBpsReadWrite, $diskProps.diskState, $disk.id, $disk.name, $disk.location, $diskProps.encryption) | Out-Null
|
|
}
|
|
|
|
$diskDT | Export-Csv -NoTypeInformation -LiteralPath $folder"\Resources\Disks.csv"
|
|
$count = $disks.count
|
|
Write-Verbose "`t$count Disks were enumerated."
|
|
|
|
#TODO: Deployments
|
|
|
|
Write-Verbose "Getting Key Vault Policies..."
|
|
|
|
$keyVaults = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/resources?`$filter=resourceType eq 'Microsoft.KeyVault/vaults'&api-version=2019-09-01"))
|
|
foreach($vault in $keyVaults){
|
|
$vaultDetails = ((Invoke-WebRequest -Uri (-join ("https://management.azure.com",$vault.id,"?api-version=2019-09-01")) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).content | convertfrom-json)
|
|
$vaultPerms = $vaultDetails.properties.accessPolicies.permissions
|
|
#Bit of a hack to expand the objects in our CSV
|
|
[pscustomobject]@{
|
|
Keys = $vaultPerms.keys -join ','
|
|
Secrets = $vaultPerms.secrets -join ','
|
|
Certificates = $vaultPerms.certificates -join ','
|
|
} | Export-Csv -NoTypeInformation -LiteralPath (-join ($folder,'\Resources\',$vault.name,'-Vault_Policies.csv'))
|
|
}
|
|
|
|
#Write-Verbose "Getting Resource Groups..."
|
|
#$resourceGroups = ((Invoke-WebRequest -uri (-join ("https://management.azure.com/subscriptions/",$SubscriptionId,"/resourcegroups?api-version=2020-10-01") ) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).content | ConvertFrom-Json).value
|
|
#foreach($rg in $resourceGroups){
|
|
# $rg | select ResourceGroupName,Location,ProvisioningState,ResourceId | Export-CSV -NoTypeInformation -LiteralPath $folder"\Resources\Resource_Groups.CSV"
|
|
#}
|
|
|
|
Write-Verbose "Getting Automation Account Runbooks and Variables..."
|
|
|
|
$automationAccounts = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com/subscriptions/",$SubscriptionId,"/providers/Microsoft.Automation/automationAccounts?api-version=2015-10-31"))
|
|
if($automationAccounts){
|
|
if(Test-Path $folder"\Resources\AutomationAccounts"){}
|
|
else{New-Item -ItemType Directory $folder"\Resources\AutomationAccounts" | Out-Null}
|
|
}
|
|
foreach($account in $automationAccounts){
|
|
if(Test-Path (-join ($folder,"\Resources\AutomationAccounts\",$account.name))){}
|
|
else{New-Item -ItemType Directory (-join ($folder,"\Resources\AutomationAccounts\",$account.name)) | Out-Null}
|
|
$runbooks = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com" + $account.id + "/runbooks?api-version=2015-10-31"))
|
|
foreach($runbook in $runbooks){
|
|
try{
|
|
$content = (Invoke-WebRequest -uri (-join ("https://management.azure.com" + $runbook.id + "/content?api-version=2015-10-31") ) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing)
|
|
if($content.Headers["Content-Type"] -eq "text/powershell"){
|
|
$content.Content | Out-File -FilePath (-join ($folder,"\Resources\AutomationAccounts\",$account.name,"\",$runbook.name,".txt"))
|
|
}
|
|
}
|
|
#We get a 404 on runbooks that haven't been published yet, might change this to just create an empty text file
|
|
catch [System.Net.WebException]{
|
|
}
|
|
}
|
|
$variables = Get-RESTReq -managementToken $managementToken -resourceURI (-join ("https://management.azure.com" + $account.id + "/variables?api-version=2015-10-31") )
|
|
$variables | Select name, properties | Out-File -FilePath (-join ($folder,"\Resources\AutomationAccounts\",$account.name,"\","Variables.txt")) #-Append
|
|
}
|
|
$count = $automationAccounts.count
|
|
Write-Verbose "`t$count Automation Accounts were enumerated."
|
|
|
|
}
|
|
|
|
if($NetworkInfo -eq "Y"){
|
|
Write-Verbose "Getting Network Interfaces..."
|
|
if(Test-Path $folder"\Interfaces"){}
|
|
else{New-Item -ItemType Directory $folder"\Interfaces\" | Out-Null}
|
|
|
|
$networkInterfaces = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.Network/networkInterfaces?api-version=2020-11-01"))
|
|
foreach($interface in $networkInterfaces){
|
|
$NICName = $interface.name
|
|
foreach($prop in $interface.properties){
|
|
$prop.ipConfigurations.properties | select PrivateIpAddressVersion,Primary,LoadBalancerBackendAddressPoolsText,LoadBalancerInboundNatRulesText,ApplicationGatewayBackendAddressPoolsText,ApplicationSecurityGroupsText,PrivateIpAddress,PrivateIpAllocationMethod,ProvisioningState,SubnetText,PublicIpAddressText,Name,Etag,Id | Export-Csv -NoTypeInformation -LiteralPath $folder"\Interfaces\"$NICName"-ipConfig.csv"
|
|
}
|
|
|
|
}
|
|
Write-Verbose("`tGetting Public IPs for each network interface...")
|
|
|
|
$publicIpTbl = New-Object System.Data.DataTable
|
|
$publicIpTbl.Columns.Add("Name") | Out-Null
|
|
$publicIpTbl.Columns.Add("IPAddress") | Out-Null
|
|
$publicIpTbl.Columns.Add("PublicIPAllocationMethod") | Out-Null
|
|
$publicIpTbl.Columns.Add("ResourceGroup") | Out-Null
|
|
|
|
$publicIps = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.Network/publicIPAddresses?api-version=2020-11-01"))
|
|
|
|
$publicIpCount = 0
|
|
foreach($ip in $publicIps){
|
|
if($ip.properties.ipAddress){
|
|
$publicIpTbl.Rows.Add($ip.name, $ip.properties.IPAddress, $ip.properties.publicIPAllocationMethod, $ip.id.split('/')[4]) | Out-Null
|
|
$publicIpCount += 1
|
|
}
|
|
}
|
|
$publicIpTbl | Export-Csv -NoTypeInformation -LiteralPath $folder"\PublicIPs.csv"
|
|
Write-Verbose("`t$publicIPCount Public IP Addresses were found")
|
|
|
|
Write-Verbose "`tGetting Network Security Groups..."
|
|
# Create data table to house results
|
|
$RulesTempTbl = New-Object System.Data.DataTable
|
|
$RulesTempTbl.Columns.Add("NSGName") | Out-Null
|
|
$RulesTempTbl.Columns.Add("ResourceGroupName") | Out-Null
|
|
$RulesTempTbl.Columns.Add("Location") | Out-Null
|
|
$RulesTempTbl.Columns.Add("RuleName") | Out-Null
|
|
$RulesTempTbl.Columns.Add("Protocol") | Out-Null
|
|
$RulesTempTbl.Columns.Add("SourcePortRange") | Out-Null
|
|
$RulesTempTbl.Columns.Add("DestinationPortRange") | Out-Null
|
|
$RulesTempTbl.Columns.Add("SourceAddressPrefix") | Out-Null
|
|
$RulesTempTbl.Columns.Add("DestinationAddressPrefix") | Out-Null
|
|
$RulesTempTbl.Columns.Add("Access") | Out-Null
|
|
$RulesTempTbl.Columns.Add("Priority") | Out-Null
|
|
$RulesTempTbl.Columns.Add("Direction") | Out-Null
|
|
|
|
$networkSecurityGroups = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.Network/networkSecurityGroups?api-version=2020-11-01"))
|
|
foreach($group in $networkSecurityGroups){
|
|
$NSGName = $group.name
|
|
$NSGRG = $group.id.split('/')[4]
|
|
$NSGLocation = $group.location
|
|
foreach($rule in $group.properties.securityRules){
|
|
$RulesTempTbl.Rows.Add($NSGName, $NSGRG, $NSGLocation, $rule.name, $rule.properties.protocol, $rule.properties.sourcePortRange -join ' ', $rule.properties.DestinationPortRange -join ' ', $rule.properties.SourceAddressPrefix -join ' ', $rule.properties.DestinationAddressPrefix -join ' ', $rule.properties.Access, $rule.properties.priority, $rule.properties.direction) | Out-Null
|
|
}
|
|
}
|
|
$RulesTempTbl | Export-Csv -NoTypeInformation -LiteralPath $folder"\FirewallRules.csv"
|
|
$RulesTempTbl | where Direction -EQ 'Inbound' | where SourceAddressPrefix -eq '*' | where Access -EQ 'Allow' | Export-Csv -NoTypeInformation -LiteralPath $folder"\FirewallRules-AnySourceInboundAllow.csv"
|
|
$RulesTempTbl | where Direction -EQ 'Inbound' | where SourceAddressPrefix -eq '*' | where Access -EQ 'Allow' | where DestinationAddressPrefix -EQ '*' | Export-Csv -NoTypeInformation -LiteralPath $folder"\FirewallRules-AnyAnyInboundAllow.csv"
|
|
$AnyAnyRules = $RulesTempTbl | where Direction -EQ 'Inbound' | where SourceAddressPrefix -eq '*' | where Access -EQ 'Allow' | where DestinationAddressPrefix -EQ '*'
|
|
$AnyRulesCounter = $AnyAnyRules | measure
|
|
$AnyRulesCount = $AnyRulesCounter.Count
|
|
|
|
$RulesCounter = $RulesTempTbl | measure
|
|
$RulesCount = $RulesCounter.Count
|
|
Write-Verbose "`t$RulesCount Network Security Group Firewall Rules were enumerated."
|
|
Write-Verbose "`t`t$AnyRulesCount Inbound 'Any Any' Network Security Group Firewall Rules were enumerated."
|
|
}
|
|
|
|
if($VMs -eq "Y"){
|
|
|
|
|
|
# Create folder for VM Info for cleaner output
|
|
if(Test-Path $folder"\VirtualMachines"){}
|
|
else{New-Item -ItemType Directory $folder"\VirtualMachines\" | Out-Null}
|
|
|
|
$virtualMachines = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.Compute/virtualMachines?api-version=2020-06-01"))
|
|
$vmDT = New-Object System.Data.DataTable("vms")
|
|
$columns = @("ResourceGroupName","Name","Location","ProvisioningState")
|
|
foreach($col in $columns){$vmDT.Columns.Add($col) | Out-Null}
|
|
foreach($vm in $virtualMachines){
|
|
$vmDetails = (Invoke-WebRequest -uri (-join ("https://management.azure.com" + $vm.id + "?api-version=2020-06-01") ) -Verbose:$false -Method GET -Headers @{ Authorization ="Bearer $managementToken"} -UseBasicParsing).content | convertfrom-json
|
|
$vmDT.Rows.Add($vmDetails.id, $vmDetails.name, $vmDetails.location, $vmDetails.properties.provisioningState) | Out-Null
|
|
}
|
|
|
|
$vmDT | Export-Csv -NoTypeInformation -LiteralPath $folder"\VirtualMachines\VirtualMachines-Basic.csv"
|
|
|
|
$count = $virtualMachines.count
|
|
Write-Verbose "`t$count Virtual Machines enumerated."
|
|
}
|
|
|
|
if($RBAC -eq "Y"){
|
|
|
|
if(Test-Path $folder"\RBAC"){}
|
|
else{New-Item -ItemType Directory $folder"\RBAC\" | Out-Null}
|
|
|
|
$principalPermissionsTbl = New-Object System.Data.DataTable
|
|
$principalPermissionsTbl.Columns.Add("PrincipalID") | Out-Null
|
|
$principalPermissionsTbl.Columns.Add("RoleName") | Out-Null
|
|
$principalPermissionsTbl.Columns.Add("Scope") | Out-Null
|
|
|
|
|
|
#Can just grab our identity's principal ID from our JWT
|
|
$tokenPayload = $managementToken.split('.')[1]
|
|
while($tokenPayload.Length % 4){$tokenPayload += "="}
|
|
$tokenJson = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($tokenPayload)) | ConvertFrom-Json
|
|
$currentPrincipalID = $tokenJson.oid
|
|
$roleDefinitions = Get-RESTReq -managementToken $managementToken -resourceURI (-join('https://management.azure.com/subscriptions/',$SubscriptionID,'/providers/Microsoft.Authorization/roleDefinitions?api-version=2015-07-01'))
|
|
$ownerGUID = ($roleDefinitions | ForEach-Object{ if ($_.properties.RoleName -eq 'Owner'){$_.name}})
|
|
$rbacAssignments = Get-RESTReq -managementToken $managementToken -resourceURI (-join ('https://management.azure.com/subscriptions/',$SubscriptionId,"/providers/Microsoft.Authorization/roleAssignments?api-version=2015-07-01"))
|
|
foreach($def in $rbacAssignments.properties){
|
|
$roleDefID = $def.roleDefinitionId.split("/")[6]
|
|
|
|
|
|
$roleName = ($roleDefinitions | foreach-object {if ($_.name -eq $roleDefID){$_.properties.RoleName}})
|
|
if($roleName){
|
|
$principalPermissionsTbl.Rows.Add($def.principalId, $roleName, $def.scope) | out-null
|
|
if($def.principalId -eq $currentPrincipalID){
|
|
Write-Verbose (-join ("Current identity has permission ", $roleName, " on scope ", $def.scope))
|
|
}
|
|
else{
|
|
#Write-Verbose (-join ("Principal ", $def.principalId, " has permission ", $roleName, " on scope ", $def.scope))
|
|
}
|
|
}
|
|
}
|
|
|
|
$readers = $principalPermissionsTbl.Select("RoleName = 'Reader'")
|
|
if($readers){$readers | Export-CSV -NoTypeInformation -LiteralPath $folder"\RBAC\Readers.csv"}
|
|
$contributors = $principalPermissionsTbl.Select("RoleName = 'Contributor'")
|
|
if($contributors){$contributors | Export-CSV -NoTypeInformation -LiteralPath $folder"\RBAC\Contributors.csv"}
|
|
$owners = $principalPermissionsTbl.Select("RoleName = 'Owner'")
|
|
if($owners){$owners | Export-CSV -NoTypeInformation -LiteralPath $folder"\RBAC\Owners.csv"}
|
|
$currentIdentityPerms = $principalPermissionsTbl.Select("PrincipalID = '$currentPrincipalID'")
|
|
if($currentIdentityPerms){$currentIdentityPerms | Export-CSV -NoTypeInformation -LiteralPath $folder"\RBAC\CurrentIdentity.csv"}
|
|
|
|
}
|
|
}
|