When you are in an environment with strict internet access, you need to figure out what to open to what destination for Microsoft services like Exchange Online, Teams, Endpoint Manager, and so on. Microsoft publishes this on their website but in the blog post, I would like to show you a nice way of outputting that information in an Out-GridView or a CSV file.
How the script works
It downloads the information from a Microsoft link that Microsoft maintains that contains all IP addresses and FQDNs with their TCP or UDP ports, after downloading it converts it from JSON to an object. Afterward, it displays the information in an Out-GridView Windows for easy sorting and filtering (You can copy your selection in the window with CTRL-C) or to a CSV if you use the CSVPath parameter.
Running the script
When running it without any parameters, it looks like this:

When running it with the -CSVPath parameter and specifying the output path, example below which saves it to d:\temp\endpoint.csv, it looks like this:
Get-MicrosoftEndpoints -CSVPath d:\temp\endpoints.csv

The script
Below is the script, you can add it to your PowerShell profile by:
notepad $profile add '. c:\scripts\get-microsoftendpoints.ps1' quit/save and start a new PowerShell session
function Get-MicrosoftEndpoints { param ( [parameter(parameterSetName = "CSV")][string]$CSVPath ) #Hide download progress, get current JSON url, retrieve all Endpoints and Convert it from JSON format $ProgressPreference = "SilentlyContinue" try { $site = Invoke-WebRequest -Uri 'https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide' -UseBasicParsing $jsonlink = ($site.Links | where-Object OuterHTML -match 'JSON formatted').href } catch { Write-Warning ("Error downloading JSON file, please check if https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide is accessible") return } try { $Endpoints = Invoke-WebRequest -Uri $jsonlink -ErrorAction Stop | ConvertFrom-Json Write-Host ("Downloading worldwide Microsoft Endpoints") -ForegroundColor Green } catch { Write-Warning ("Error downloading worldwide Microsoft Endpoints, please check if $($jsonlink) is accessible") return } Write-Host ("Processing items...") -ForegroundColor Green $Total = foreach ($Endpoint in $Endpoints) { #Check if IPs are available for the Endpoint, set to not available if not if (-not $Endpoint.ips) { $IPaddresses = 'Not available' } else { $IPaddresses = $Endpoint.ips.split(' ') -join ', ' } #Check if TCP ports are available for the Endpoint, set to not available if not if (-not $Endpoint.tcpPorts) { $TCPPorts = 'Not available' } else { $TCPPorts = $Endpoint.TCPPorts.split(',') -join ', ' } #Check if UDP ports are available for the Endpoint, set to not available if not if (-not $Endpoint.udpPorts) { $UDPPorts = 'Not available' } else { $UDPPorts = $Endpoint.udpPorts.split(',') -join ', ' } #Check if there are notes for the Endpoint, set to not available if not if (-not $Endpoint.notes) { $Notes = 'Not available' } else { $Notes = $Endpoint.Notes } #Check if URLs are available for the Endpoint, set to not available if not if (-not $Endpoint.urls) { $URLlist = 'Not available' } else { $URLlist = $Endpoint.urls -join ', ' } [PSCustomObject]@{ serviceArea = $Endpoint.serviceArea serviceAreaDisplayName = $Endpoint.serviceAreaDisplayName urls = $URLlist ips = $IPaddresses tcpPorts = $TCPPorts udpPorts = $UDPPorts notes = $notes expressRoute = $Endpoint.expressRoute category = $Endpoint.Category required = $Endpoint.required } } #Export data to specified $CSVPath if specified if ($CSVPath) { try { New-Item -Path $CSVPath -ItemType File -Force:$true -ErrorAction Stop | Out-Null $Total | Sort-Object serviceAreaDisplayName | Export-Csv -Path $CSVPath -Encoding UTF8 -Delimiter ';' -NoTypeInformation Write-Host ("Saved results to {0} `nDone!" -f $CSVPath) -ForegroundColor Green } catch { Write-Warning ("Could not save results to {0}" -f $CSVPath) } } else { #Export to Out-Gridview Write-Host ("Exporting results to Out-GridView `nDone!") -ForegroundColor Green $Total | Sort-Object serviceAreaDisplayName | Out-GridView -Title 'Microsoft Endpoints Worldwide' } }
Download the script(s) from GitHub here
You should include UUID generation in your script as it mentions on the page here: https://learn.microsoft.com/en-us/microsoft-365/enterprise/microsoft-365-ip-web-service?view=o365-worldwide. The UUID used in your example may become unusable in the future, which will break all the script for all the people who’re using it!
Yep, you’re right and I did mention it too in the post 😊 I’ve did a blog earlier in which I retrieved the current link, will update this one later with the same method
I changed the script so that it checks for the current JSON link, this makes it more dynamic in case the download link changes on the page.
Pingback: PowerShell is fun :) Test if Microsoft services TCP ports are accessible
Pingback: PowerShell is fun :) Overview of 2022 posts
you have a typo on the suggestion for the profile edit. “add ‘. c:\scripts\get-microsoftendpoints.csv’” should presumably be add ‘. c:\scripts\get-microsoftendpoints.ps1’
You’re right! Thanks, updated it now 😅