Drew Robinson's Blog

Azure, Powershell and Security things

Azure Rest API, GET AzureRM Virtual Machine status

#Draft, will be updating this with more text and images.

The following script will quickly execute REST calls to Azure APIs to build the following output, works across subscriptions

Code:

  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
<# 
 
.SYNOPSIS  

Script uses Azure REST APIs to build a table providing Azure VM Status across multiple subscriptions
.Table contents
..VMName
..Powerstate
..VMSize
..FQN
..PublicIP
..PrivateIP
..ProvisioningStatus
..Location
..Last4ofSub

.REFERENCE
Azure APIs https://docs.microsoft.com/en-us/rest/api/

.NOTES

.Dev Drew Robinson
.Version 1
.Requirements
..[Your tenantname].onmicrosoft.com (line 36)
..Service Principal must be created and granted read access to the resource (client ID, Client Secret) (line 37,38)
    Reference: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
    Reader role for GET requests 
..Subscription IDs, "[subscriptionid1]","[subscriptionid2]","[subscriptionid3]",etc (line 39)


#>


# Vars 
$Tenant="[Your Tenant Domain Name].onmicrosoft.com"
$ClientID="[Your Client ID from Azure AD Application Registration x-x-x-x-x"
$ClientSecret="[Your Client Secret from Azure AD Application Registration xxxxxxxxxxxxxxxxxxx="
$SubscriptionIDs=("[subscriptionid1]","[subscriptionid2]","[subscriptionid3]",etc)


#Create Table

$table = New-Object system.Data.DataTable 'table'
$C1 = New-Object system.Data.DataColumn VMName,([string]);$table.columns.add($C1)
$C2 = New-Object system.Data.DataColumn Powerstate,([string]);$table.columns.add($C2)
$C3 = New-Object system.Data.DataColumn VMSize,([string]);$table.columns.add($C3)
$C4 = New-Object system.Data.DataColumn PublicIP,([string]);$table.columns.add($C4)
$C5 = New-Object system.Data.DataColumn PrivateIP,([string]);$table.columns.add($C5)
$C6 = New-Object system.Data.DataColumn ProvisioningState,([string]);$table.columns.add($C6)
$C7 = New-Object system.Data.DataColumn Location,([string]);$table.columns.add($C7)
$C8 = New-Object system.Data.DataColumn Last4ofSub,([string]);$table.columns.add($C8)
$C9 = New-Object system.Data.DataColumn FQN,([string]);$table.columns.add($C9)


# Generate Token that will be used for API access
$Token = Invoke-RestMethod -Uri https://login.microsoftonline.com/$tenant/oauth2/token?api-version=1.0 -Method Post -Body @{"grant_type" = "client_credentials"; "resource" = "https://management.core.windows.net/"; "client_id" = $ClientID; "client_secret" = $ClientSecret}

    Foreach ($SubscriptionID in $SubscriptionIDs){

            # API Endpoint we are accessing 
            $VirtualMachines="https://management.azure.com/subscriptions/$SubscriptionID/providers/Microsoft.Compute/virtualmachines/?api-version=2017-03-30"
            
            # Request for all VMS
            $Request = Invoke-RestMethod -Header @{'authorization'="Bearer $($Token.access_token)"} -URI $VirtualMachines -UserAgent 'application/json' -Method Get

                Foreach ($VM in $Request.value){
            
                        #Get ResourceGroupName
                        $ResourceGroup="https://management.azure.com/subscriptions/$Subscriptionid/resourceGroups/"+($vm.id.split('/')[4])+"/providers/Microsoft.Compute/virtualMachines/"+($vm.id.split("/")[8])+"?$expand=instanceView&api-version=2017-03-30"
                        $Request2 = Invoke-RestMethod -Header @{'authorization'="Bearer $($Token.access_token)"} -URI $ResourceGroup -UserAgent 'application/json' -Method Get
            
                        #Get Network Interfaces
                        $NetworkInterfaces="https://management.azure.com"+$request2.properties.networkprofile.networkinterfaces.id+"/?api-version=2017-03-01"
                        $Request3 = Invoke-RestMethod -Header @{'authorization'="Bearer $($Token.access_token)"} -URI $NetworkInterfaces -UserAgent 'application/json' -Method Get

                        #GetIPConfig
                        $IPConfig="https://management.azure.com"+$Request3.properties.ipConfigurations.id+"/?api-version=2017-03-01"
                        $Request4 = Invoke-RestMethod -Header @{'authorization'="Bearer $($Token.access_token)"} -URI $IPConfig -UserAgent 'application/json' -Method Get

                        #GetPublicIPConfig
                        $PublicIP="https://management.azure.com"+$request4.properties.publicIPAddress.id+"/?api-version=2017-03-01"
                        $Request5 = Invoke-RestMethod -Header @{'authorization'="Bearer $($Token.access_token)"} -URI $PublicIP -UserAgent 'application/json' -Method Get
      
                        $Instanceview="https://management.azure.com/subscriptions/$Subscriptionid/resourceGroups/"+$resourcegroup.split("/")[6]+"/providers/Microsoft.Compute/virtualMachines/"+$vm.name+"/instanceView/?api-version=2017-03-30"
                        $Request6 = Invoke-RestMethod -Header @{'authorization'="Bearer $($Token.access_token)"} -URI $Instanceview -UserAgent 'application/json' -Method Get
                        

                        $row = $table.NewRow()
                        $row.VMName=$VM.name
                        $row.VMSize=$Request2.properties.hardwareprofile.vmsize
                        $row.PowerState=$Request6.statuses.code[1].split("/")[1]
                        $row.PublicIP=$Request5.properties.ipAddress
                        $row.PrivateIP=$request4.properties.privateIPAddress 
                        $row.Location=$vm.location 
                        $row.ProvisioningState=$vm.properties.provisioningState
                        $row.Last4ofSub=($vm.id.split("/")[2])| % {$_.substring($_.length-4)}
                        $row.FQN=$Request5.properties.dnsSettings.fqdn
                        $table.Rows.Add($row)


                        

                                            
                }

    }


    $table |ft