Skip to content

Control 2.15: Network Security and Private Connectivity — PowerShell Setup

Automation scripts for verifying and monitoring network security for Copilot connectivity.

Prerequisites

  • Microsoft Graph PowerShell SDK
  • Azure PowerShell module (only for verifying Private Link on adjacent Azure resources an internal agent calls — not for M365 Copilot)
  • Network Administrator role

Scripts

Script 1: Microsoft 365 Endpoint Connectivity Test

# Test connectivity to representative Microsoft 365 service endpoints.
# This is a diagnostic sample, not a firewall allowlist or a functional WSS test.
# Requires: Network access from the test machine

$endpoints = @(
    @{ Name = "SharePoint Online"; URL = "<tenant>.sharepoint.com"; Port = 443 },
    @{ Name = "Exchange Online"; URL = "outlook.office365.com"; Port = 443 },
    @{ Name = "Teams"; URL = "teams.microsoft.com"; Port = 443 },
    @{ Name = "Graph API"; URL = "graph.microsoft.com"; Port = 443 }
)

$results = @()
foreach ($ep in $endpoints) {
    $test = Test-NetConnection -ComputerName $ep.URL -Port $ep.Port -WarningAction SilentlyContinue
    $results += [PSCustomObject]@{
        Endpoint     = $ep.Name
        URL          = $ep.URL
        Port         = $ep.Port
        Reachable    = $test.TcpTestSucceeded
        LatencyMs    = $test.PingReplyDetails.RoundtripTime
        RemoteAddress = $test.RemoteAddress
    }
}

Write-Host "=== M365 Copilot Endpoint Connectivity ==="
$results | Format-Table Endpoint, Reachable, LatencyMs -AutoSize
$results | Export-Csv "EndpointConnectivity_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation

$failures = ($results | Where-Object { -not $_.Reachable }).Count
if ($failures -gt 0) {
    Write-Host "WARNING: $failures endpoints unreachable!" -ForegroundColor Red
}

Use the Microsoft 365 endpoint web service for firewall configuration. Separately verify full WSS connectivity to the published Copilot domains, *.cloud.microsoft and *.office.com; Test-NetConnection to a few representative hosts does not validate wildcard coverage or the WebSocket protocol.

# Enumerate Azure Private Link endpoints for ADJACENT Azure resources an internal
# Copilot Studio agent calls (e.g., an Azure-hosted API, Azure SQL, Storage).
# Azure Private Link does NOT apply to M365 Copilot: Microsoft 365 (SharePoint
# Online, Exchange Online, Teams, Copilot) is internet-facing SaaS with no
# customer-managed private endpoints. Do not expect M365/Copilot endpoints here.
# Requires: Azure PowerShell module

Import-Module Az.Network
Connect-AzAccount

$privateEndpoints = Get-AzPrivateEndpoint

if ($privateEndpoints.Count -gt 0) {
    Write-Host "=== Azure Private Link Status (adjacent Azure resources) ==="
    foreach ($pe in $privateEndpoints) {
        Write-Host "Name: $($pe.Name)"
        Write-Host "  Status: $($pe.ProvisioningState)"
        Write-Host "  Subnet: $($pe.Subnet.Id)"
        Write-Host "  Connection: $($pe.PrivateLinkServiceConnections.PrivateLinkServiceConnectionState.Status)"
        Write-Host ""
    }
} else {
    Write-Host "No Azure Private Link endpoints configured."
    Write-Host "Private Link is not applicable to M365 Copilot SaaS; use it only for"
    Write-Host "adjacent Azure resources (e.g., an Azure-hosted API an internal agent calls)."
}

Script 3: Named Location Configuration Audit

# Audit Conditional Access named locations for network security
Import-Module Microsoft.Graph.Identity.SignIns
Connect-MgGraph -Scopes "Policy.Read.All"

$locations = Get-MgIdentityConditionalAccessNamedLocation
$locationReport = @()

foreach ($loc in $locations) {
    $type = $loc.AdditionalProperties["@odata.type"]
    $trusted = $loc.AdditionalProperties["isTrusted"]
    $locationReport += [PSCustomObject]@{
        Name      = $loc.DisplayName
        Type      = $type
        IsTrusted = $trusted
        Created   = $loc.CreatedDateTime
        Modified  = $loc.ModifiedDateTime
    }
}

Write-Host "=== Named Locations for Network Security ==="
$locationReport | Format-Table Name, Type, IsTrusted -AutoSize
$locationReport | Export-Csv "NamedLocations_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation

Scheduled Tasks

Task Frequency Purpose
Endpoint Connectivity Test Daily Verify Copilot endpoint accessibility
Private Link Status Check Weekly Monitor Private Link health for adjacent Azure resources (if any)
Named Location Audit Quarterly Verify network location definitions

Next Steps