Watchlists/UpdateCloudIPs/AzureFunctionUpdateCloudIPs/UpdateCloudIPs/run.ps1 (529 lines of code) (raw):
# Input bindings are passed in via param block.
param($Timer)
# Get the current universal time in the default string format
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' porperty is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
#Functions
#Try to get the Watchlist
function Check-Watchlist {
# Parameter help description
param(
[Parameter(Mandatory)]
[string]$watchlistAlias,
[string]$resourceURI = $resourceURI,
[string]$subscriptionId = $subscriptionId,
[string]$resourceGroupName = $resourceGroupName,
[string]$workspaceName = $workspaceName
)
$Uri = $resourceURI + "/subscriptions/" + $subscriptionId + "/resourceGroups/" + $resourceGroupName + "/providers/Microsoft.OperationalInsights/workspaces/" + $workspaceName + "/providers/Microsoft.SecurityInsights/watchlists/" + $watchlistAlias + "?api-version=2021-03-01-preview"
$new = $false
try {
$IPWatchlist = Invoke-RestMethod -Method GET -Headers $requestHeaders -Uri $Uri
}
catch {
$new = $true
}
return $new
}
# Get Azure IP Ranges
function Get-AzureIPRanges {
param(
[string]$resourceURI = $resourceURI,
[string]$subscriptionId = $subscriptionId,
$requestHeaders = $requestHeaders
)
$Uri = $resourceURI + "/subscriptions/" + $subscriptionId + "/providers/Microsoft.Network/locations/centralus/serviceTags?api-version=2020-11-01"
$AzureIPRanges = Invoke-RestMethod -Method Get -Headers $requestHeaders -Uri $Uri
#add nextlink logic
return ($AzureIPRanges.values)
}
#Get AWS IP Ranges
function Get-AWSIPRanges {
$Uri = "https://ip-ranges.amazonaws.com/ip-ranges.json"
$AWSIPRanges = (Invoke-WebRequest $Uri ).Content | ConvertFrom-Json
return ($AWSIPRanges.prefixes)
}
#Get GCP IP Ranges
function Get-GCPIPRanges {
$Uri = "https://www.gstatic.com/ipranges/cloud.json"
$GCPIPRanges = (Invoke-WebRequest $uri).Content | ConvertFrom-Json
return ($GCPIPRanges.prefixes)
}
# Watchlist table
function Get-WatchlistItemTable {
# Parameter help description
param(
[Parameter(Mandatory)]
[string]$watchlistAlias,
[string]$resourceURI = $resourceURI,
[string]$subscriptionId = $subscriptionId,
[string]$resourceGroupName = $resourceGroupName,
[string]$workspaceName = $workspaceName
)
$nextLink = $true
$Uri = $resourceURI + "/subscriptions/" + $subscriptionId + "/resourceGroups/" + $resourceGroupName + "/providers/Microsoft.OperationalInsights/workspaces/" + $workspaceName + "/providers/Microsoft.SecurityInsights/watchlists/" + $watchlistAlias + "/watchlistItems?api-version=2021-03-01-preview"
$WatchListItems = Invoke-RestMethod -Method Get -Headers $requestHeaders -Uri $Uri
$WatchListItemsCollection = $WatchListItems.value
$a = 0
do {
if (($WatchListItems.nextLink) -eq $null) {
$nextLink = $false
}
else {
$Uri = $WatchListItems.nextLink
$WatchListItems = Invoke-RestMethod -Method Get -Headers $requestHeaders -Uri $Uri
$WatchListItemsCollection += $WatchListItems.value
}
$a++
#write-host "Fetching another 100, this is number $($a) time"
} until ($nextLink -eq $false)
#Build Table from all the results
$WatchListItemsTable = @()
foreach ($item in $WatchListItemsCollection) {
$WatchListItemsTableObject = New-Object psobject
$WatchListItemsTableObject | Add-Member -MemberType NoteProperty -Name "IPRange" -Value ($item.properties.itemsKeyValue.IpRange)
$WatchListItemsTableObject | Add-Member -MemberType NoteProperty -Name "Notes" -Value ($item.properties.itemsKeyValue.Notes)
$WatchListItemsTableObject | Add-Member -MemberType NoteProperty -Name "Expiration" -Value ($item.properties.itemsKeyValue.Expiration)
$WatchListItemsTableObject | Add-Member -MemberType NoteProperty -Name "ItemId" -Value ($item.Name)
$WatchListItemsTable += $WatchListItemsTableObject
}
return $WatchListItemsTable
}
#Add Watchlist Item
function Add-WatchlistItem{
param(
[string]$watchlistAlias,
[string]$watchlistitem,
[string]$Notes,
[string]$resourceURI = $resourceURI,
[string]$subscriptionId = $subscriptionId,
[string]$resourceGroupName = $resourceGroupName,
[string]$workspaceName = $workspaceName,
$requestHeaders = $requestHeaders,
$date = $date
)
$body = @{
"properties" = @{
"itemsKeyValue" = @{
"IPRange" = "$watchlistitem"
"Expiration" = "$Date"
"Notes" = "$Notes"
}
}
}
$body = $body | ConvertTo-Json
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"/watchlistItems/"+$watchlistitem+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
}
#Compare Watchlist Table to Ip Range Table
function Compare-WatchlistToTable {
param (
$WatchlistTable,
$RangeTable,
$Property
)
$results = Compare-Object $WatchlistTable $RangeTable -Property $Property -IncludeEqual -PassThru
return $results
}
#Delete Watchlist Item
function Remove-WatchlistItem{
param (
[string]$watchlistAlias,
[string]$watchlistitem,
[string]$resourceURI = $resourceURI,
[string]$subscriptionId = $subscriptionId,
[string]$resourceGroupName = $resourceGroupName,
[string]$workspaceName = $workspaceName,
$requestHeaders = $requestHeaders
)
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"/watchlistItems/"+$watchlistitem+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Delete -Headers $requestHeaders -Uri $Uri
}
#Update Watchlist Item
function Update-WatchlistItem{
param(
[string]$watchlistAlias,
[string]$watchlistitem,
[string]$resourceURI = $resourceURI,
[string]$subscriptionId = $subscriptionId,
[string]$resourceGroupName = $resourceGroupName,
[string]$workspaceName = $workspaceName,
$requestHeaders = $requestHeaders,
$date = $date
)
$body = @{
"properties" = @{
"itemsKeyValue" = @{
"IPRange" = "$watchlistitem"
"Expiration" = "$Date"
}
}
}
$body = $body | ConvertTo-Json
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"/watchlistItems/"+$watchlistitem+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
}
#Prepare Variables
$subscriptionId = $env:SubscriptionId
$resourceGroupName = $env:ResourceGroupName
$workspaceName = $env:workspaceName
$resourceURI = $env:resourceURI
$tokenAuthURI = $env:IDENTITY_ENDPOINT + "?resource=$resourceURI&api-version=2019-08-01"
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"X-IDENTITY-HEADER"="$env:IDENTITY_HEADER"} -Uri $tokenAuthURI
$accessToken = $tokenResponse.access_token
$requestHeaders = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}
$Date = (Get-Date).AddDays(7) | Get-Date -Format yyyy-MM-ddT00:00:00Z
# Main
if ($env:AWS -eq "Yes") {
Write-Host "AWS is enabled, processing..."
$watchlistAlias = "AWSIPRanges"
$new = Check-Watchlist -watchlistAlias $watchlistAlias
if ($new -eq $true) {
Write-Host "No existing AWS IP watchlist found, building it"
$AWSIPRanges = Get-AWSIPRanges
$totalCount = $AWSIPRanges.Count
$a = 0
$b = 0
$rawContent = "IPRange,Expiration,Notes`r`n"
foreach($item in $AWSIPRanges){
$range = $item.ip_prefix
$serviceName = $item.service
$rawContent += "$range,$Date,$serviceName`r`n"
$a++
$b++
if($a -eq 100){
Write-Host "$b entries of $totalCount processed"
$a = 0
}
}
Write-Host "$b entries with total of $totalCount GCP IP Ranges"
#Write to Watchlist
$body = @{
"properties" = @{
"displayName" = "AWSIPRanges"
"provider" = "AWS"
"source" = "https://ip-ranges.amazonaws.com/ip-ranges.json"
"itemsSearchKey" = "IPRange"
"rawContent" = "$rawContent"
"contentType" = "Text/csv"
"numberOfLinesToSkip" = 0
}
}
$body = $body | ConvertTo-Json
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
if (($response.id) -ne "" -or ($response.id) -ne $null) {
Write-Host "Created new AWS IP watchlist with all ranges."
}
else {
Write-Host "Creation of the watchlist may have errored"
}
}
elseif ($new -eq $false) {
Write-Host "Found existing AWS watchlist"
#build tables
$AWSIPRanges = Get-AWSIPRanges
$AWSIPRangesTable = @()
$totalCount = $AWSIPRanges.Count
$a = 0
$b = 0
$c = 0
foreach($item in $AWSIPRanges){
$range = $item.ip_prefix
$serviceName = $item.service
$AWSIPRangesTableObject = New-Object psobject
$AWSIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "IPRange" -Value $range
$AWSIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "Notes" -Value $serviceName
$AWSIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "ItemId" -Value ""
$AWSIPRangesTable += $AWSIPRangesTableObject
$a++
$b++
$c++
if($a -eq 100){
#Write-Host "$b entries of $totalCount processed"
$a = 0
}
}
Write-Host "$b entries with total of $c AWS IP Ranges"
#Build Watchlist Table
$WatchListItemsTable = Get-WatchlistItemTable -watchlistAlias $watchlistAlias
#Compare Watchlist Table to Ip Range Table
$compareResults = Compare-WatchlistToTable -WatchlistTable $WatchListItemsTable -RangeTable $AWSIPRangesTable -Property "IPRange"
$rawContent = "IPRange,Expiration,Notes`r`n"
foreach ($compareresult in $compareResults) {
if (($compareresult.SideIndicator) -eq "==" -or ($compareresult.SideIndicator) -eq "=>") {
#Update Expiration since it was in both lists
#Write-Host "Updating expiration for $($compareresult.IPRange)" -ForegroundColor Blue
$rawContent += "$($compareresult.IpRange),$Date,$($compareresult.Notes)`r`n"
}
}
$body = @{
"properties" = @{
"displayName" = "AWSIPRanges"
"provider" = "AWS"
"source" = "https://ip-ranges.amazonaws.com/ip-ranges.json"
"itemsSearchKey" = "IPRange"
"rawContent" = "$rawContent"
"contentType" = "Text/csv"
"numberOfLinesToSkip" = 0
}
}
$body = $body | ConvertTo-Json
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
if (($response.id) -ne "" -or ($response.id) -ne $null) {
Write-Host "Updated AWS IP watchlist."
}
else {
Write-Host "Updating of the watchlist may have errored"
}
}
}
if ($env:GCP -eq "Yes") {
Write-Host "GCP is enabled, processing..."
$watchlistAlias = "GCPIPRanges"
$new = Check-Watchlist -watchlistAlias $watchlistAlias
if ($new -eq $true) {
Write-Host "No existing GCP IP watchlist found, building it"
$GCPIPRanges = Get-GCPIPRanges
$totalCount = $GCPIPRanges.Count
$a = 0
$b = 0
$rawContent = "IPRange,Expiration,Notes`r`n"
foreach($item in $GCPIPRanges){
if ($item.ipv4Prefix) {
$range = $item.ipv4Prefix
}
if ($item.ipv6prefix) {
$range = $item.ipv6prefix
}
$serviceName = $item.service
$rawContent += "$range,$Date,$serviceName`r`n"
$a++
$b++
if($a -eq 100){
Write-Host "$b entries of $totalCount processed"
$a = 0
}
}
Write-Host "$b entries with total of $totalCount GCP IP Ranges"
#Write to Watchlist
$body = @{
"properties" = @{
"displayName" = "GCPIPRanges"
"provider" = "Google"
"source" = "https://www.gstatic.com/ipranges/cloud.json"
"itemsSearchKey" = "IPRange"
"rawContent" = "$rawContent"
"contentType" = "Text/csv"
"numberOfLinesToSkip" = 0
}
}
$body = $body | ConvertTo-Json
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
if (($response.id) -ne "" -or ($response.id) -ne $null) {
Write-Host "Created new GCP IP watchlist with all ranges."
}
else {
Write-Host "Creation of the watchlist may have errored"
}
}
elseif ($new -eq $false) {
Write-Host "Found existing GCP watchlist"
#build tables
$GCPIPRanges = Get-GCPIPRanges
$GCPIPRangesTable = @()
$totalCount = $GCPIPRanges.Count
$a = 0
$b = 0
$c = 0
foreach($item in $GCPIPRanges){
if ($item.ipv4Prefix) {
$range = $item.ipv4Prefix
}
if ($item.ipv6prefix) {
$range = $item.ipv6prefix
}
$serviceName = $item.service
$GCPIPRangesTableObject = New-Object psobject
$GCPIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "IPRange" -Value $range
$GCPIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "Notes" -Value $serviceName
$GCPIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "ItemId" -Value ""
$GCPIPRangesTable += $GCPIPRangesTableObject
$a++
$b++
$c++
if($a -eq 100){
#Write-Host "$b entries of $totalCount processed"
$a = 0
}
}
Write-Host "$b entries with total of $c GCP IP Ranges"
#Build Watchlist Table
$WatchListItemsTable = Get-WatchlistItemTable -watchlistAlias $watchlistAlias
#Compare Watchlist Table to Ip Range Table
$compareResults = Compare-WatchlistToTable -WatchlistTable $WatchListItemsTable -RangeTable $GCPIPRangesTable -Property "IPRange"
$rawContent = "IPRange,Expiration,Notes`r`n"
foreach ($compareresult in $compareResults) {
if (($compareresult.SideIndicator) -eq "==" -or ($compareresult.SideIndicator) -eq "=>") {
#Update Expiration since it was in both lists
#Write-Host "Updating expiration for $($compareresult.IPRange)" -ForegroundColor Blue
$rawContent += "$($compareresult.IpRange),$Date,$($compareresult.Notes)`r`n"
}
}
$body = @{
"properties" = @{
"displayName" = "GCPIPRanges"
"provider" = "Goolge"
"source" = "https://www.gstatic.com/ipranges/cloud.json"
"itemsSearchKey" = "IPRange"
"rawContent" = "$rawContent"
"contentType" = "Text/csv"
"numberOfLinesToSkip" = 0
}
}
$body = $body | ConvertTo-Json
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
if (($response.id) -ne "" -or ($response.id) -ne $null) {
Write-Host "Updated GCP IP watchlist with all ranges."
}
else {
Write-Host "Updating of the watchlist may have errored"
}
}
}
if ($env:Azure -eq "Yes") {
Write-Host "Azure is enabled, processing..."
$watchlistAlias = "AzureIPRanges"
$new = Check-Watchlist -watchlistAlias $watchlistAlias
if ($new -eq $true) {
Write-Host "No existing Azure IP watchlist found, building it"
$AzureIPRanges = (Get-AzNetworkServiceTag -location centralus).Values
$totalCount = $AzureIPRanges.Count
$a = 0
$b = 0
$c = 0
$rawContent = "IPRange,Expiration,Notes`r`n"
foreach($item in $AzureIPRanges){
if(($item.properties.region) -eq ""){
If(($item.properties.systemService) -eq ""){
$serviceName = $item.Id
}
else {
$serviceName = $Item.properties.systemService
}
foreach ($range in ($item.properties.addressPrefixes)){
$rawContent += "$range,$Date,$serviceName`r`n"
$c++
}
}
$a++
$b++
if($a -eq 100){
Write-Host "$b entries of $totalCount processed"
$a = 0
}
}
Write-Host "$b entries with total of $c Azure IP Ranges"
#Write to Azure Watchlist
$body = @{
"properties" = @{
"displayName" = "AzureIPRanges"
"provider" = "Microsoft"
"source" = "https://docs.microsoft.com/rest/api/virtualnetwork/service-tags/list"
"itemsSearchKey" = "IPRange"
"rawContent" = "$rawContent"
"contentType" = "Text/csv"
"numberOfLinesToSkip" = 0
}
}
$body = $body | ConvertTo-Json
#create function
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
if (($response.id) -ne "" -or ($response.id) -ne $null) {
Write-Host "Created new Azure IP watchlist with all ranges."
}
else {
Write-Host "Creation of the watchlist may have errored"
}
}
elseif ($new -eq $false) {
Write-Host "Found existing Azure watchlist"
#build tables
$AzureIPRanges = (Get-AzNetworkServiceTag -location centralus).Values
$AzureIPRangesTable = @()
$totalCount = $AzureIPRanges.Count
$a = 0
$b = 0
$c = 0
foreach($item in $AzureIPRanges){
if(($item.properties.Region) -eq ""){
If(($item.properties.systemService) -eq ""){
$serviceName = $item.Id
}
else {
$serviceName = $Item.properties.systemService
}
foreach ($range in ($item.properties.addressPrefixes)){
$AzureIPRangesTableObject = New-Object psobject
$AzureIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "IPRange" -Value $range
$AzureIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "Notes" -Value $serviceName
$AzureIPRangesTableObject | Add-Member -MemberType NoteProperty -Name "ItemId" -Value ""
$AzureIPRangesTable += $AzureIPRangesTableObject
$c++
}
}
$a++
$b++
if($a -eq 100){
Write-Host "$b entries of $totalCount processed"
$a = 0
}
}
Write-Host "$b entries with total of $c Azure IP Ranges"
#Build Watchlist Table
$WatchListItemsTable = Get-WatchlistItemTable -watchlistAlias $watchlistAlias
#Compare Watchlist Table to Ip Range Table
$compareResults = Compare-WatchlistToTable -WatchlistTable $WatchListItemsTable -RangeTable $AzureIPRangesTable -Property "IPRange"
$rawContent = "IPRange,Expiration,Notes`r`n"
foreach ($compareresult in $compareResults) {
if (($compareresult.SideIndicator) -eq "==" -or ($compareresult.SideIndicator) -eq "=>") {
#Update Expiration since it was in both lists
#Write-Host "Updating expiration for $($compareresult.IPRange)" -ForegroundColor Blue
$rawContent += "$($compareresult.IpRange),$Date,$($compareresult.Notes)`r`n"
}
}
$body = @{
"properties" = @{
"displayName" = "AzureIPRanges"
"provider" = "Microsoft"
"source" = "https://docs.microsoft.com/en-us/rest/api/virtualnetwork/service-tags/list"
"itemsSearchKey" = "IPRange"
"rawContent" = "$rawContent"
"contentType" = "Text/csv"
"numberOfLinesToSkip" = 0
}
}
$body = $body | ConvertTo-Json
#create function
$Uri = $resourceURI+"/subscriptions/"+$subscriptionId+"/resourceGroups/"+$resourceGroupName+"/providers/Microsoft.OperationalInsights/workspaces/"+$workspaceName+"/providers/Microsoft.SecurityInsights/watchlists/"+$watchlistAlias+"?api-version=2021-03-01-preview"
$response = Invoke-RestMethod -Method Put -Headers $requestHeaders -Uri $Uri -Body $body
if (($response.id) -ne "" -or ($response.id) -ne $null) {
Write-Host "Updated Azure IP watchlist with all ranges."
}
else {
Write-Host "Updating of the watchlist may have errored"
}
}
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"