This post will show you how to use the powerful Azure Resource Graph extension with Azure CLI to pull all kinds of useful security information across multiple subscriptions.
I have a customer with a handful of Azure subscriptions that needs to conduct a holistic security audit of their Azure footprint. To do this they want to know how many resources have public IPs, what are the public IPs, and what are the NSGs in the environment.
Using Powershell scripts across multiple subscriptions is a bit of a pain and doesn't show you the WebApps addresses at all so I am going to use the Azure Resource Graph tool set. In order to do this we need to use Azure CLI which I have installed on my linux box as shown in the howto below:
Next, we need to add the Resource Graph extension to the Azure CLI environment.
az extension add --name resource-graph
The installed extension 'resource-graph' is in preview.
# Check the extension list (note that you may have other extensions installed)
az extension list
We can run some simple queries like the following resource list. The resource graph commands have a default limit of 100 to prevent you from causing too much trouble accidentally. So once you get the hang of things be sure to override the default limits with the "--first 500" command.
az graph query -q 'Resources | project name, type | limit 5'
{
"name": "COMPANYDC04",
"type": "microsoft.compute/virtualmachines"
},
{
"name": "SqlServer1",
"type": "microsoft.compute/virtualmachines"
}
...
The output of the command is in JSON by default. Feel free to change this to fit your needs with the "--output {json, jsonc, tsv, table}"
Now we are ready to get into the meat and potatoes. Let's run a command across all of our resources to show us the public IP field as long as it's not blank. We will export this data as a table including the resource group name of the item.
az graph query -q "Resources | where type contains 'publicIPAddresses' and isnotempty(properties.ipAddress) | project name, resourceGroup, properties.ipAddress | sort by name" --first 200 --output table
Name Properties_ipAddress ResourceGroup
------------------------------------------- ---------------------- ---------------------------
CompADFSPRXY-ip 40.222.229.65 Compadfsprxy-rg
CompADFS-ip 204.220.52.82 Compadfs-rg
Comp-SFTP-ip 23.86.254.220 itoperationsresourcegroup
SONARQUBE-ip 40.83.224.39 rg_sonarqube_poc
QA-ASE-FWIP 20.284.252.95 qa-ase-pay-rg
...
This is great information! Lets put this in to an excel file and gather some more data.
I want to find the list of all NSGs deployed to the tenant and then make sure that each of the public IPs listed above are covered with an NSG.
az graph query -q "Resources | where type=~ 'microsoft.network/networksecuritygroups' | mv-expand rules=properties.securityRules | project rules.name, rules.properties.access, rules.properties.destinationPortRange, name, resourceGroup | sort by name" --first 500 --output table
Name ResourceGroup Rules_name Rules_properties_access Rules_properties_destinationPortRange
-------------------------- --------------------------------------------------
NSG_Artifact rg_dev_omega Port_443 Allow 443
NSG_Artifact rg_dev_omega Port_8081 Allow 8081
...
Now take this information and put it on a second tab in excel. Rearrange the columns so that "Resource Group" is in column A and NSG Name is in column B.
Then we will add a new column to the first tab with the public IPs and call it "NGS Applied". We will use an =VLOOKUP command to pull the data from the NSG tab and insert it here. The excact command is:
=VLOOKUP(C2,'NSG Rules'!$A$3:$B$224,2,FALSE)
Copy and paste this formula to the rest of the fields in this column to easily see which Resource Groups have NSGs applied to them.
One more thing... Web Apps do not show up with the same public IP field shown above. It takes a special command to devine the every changing IP address of a PaaS webapp.
az graph query -q "Resources | where type =~ 'Microsoft.Web/Sites' | project name, resourceGroup, properties.defaultHostName, properties.inboundIpAddress | sort by name" --first 500 --output table
Name Properties_defaultHostName Properties_inboundIpAddress ResourceGroup
----------------------------------------- ---------------------------------
dev-app-WUS dev-app-wus.azurewebsites.net 40.222.243.240 dev-rg-wus
COM-DEV-Web COM-dev-web.azurewebsites.net 40.80.256.205 rg_dev_omega
DEV-COM-WUS-SYSAPI dev-com-sysapi.azurewebsites.net 52.260.40.228 dev-com-rg-wus
...
WebApps by default have NSGs that only permit port 80 and 443. We could also query accross the webapps to see if https only is enabled for each but I'm not going to get in to that here.
-Brett
Reference:
Comments