Skip to main content

Appendix D.2: AVD Firewall Reference

This appendix provides the Azure Firewall rule reference for Azure Virtual Desktop deployments in GCC High. Rules use Microsoft-maintained FQDN tags wherever they exist and explicit FQDNs only where no tag is available. For architecture context and the network topology, see Scenario: Azure Virtual Desktop.

Commercial equivalents

This appendix targets GCC High deployments. Microsoft's FQDN tags (WindowsVirtualDesktop, Office365, MicrosoftIntune, WindowsUpdate, WindowsDiagnostics, MicrosoftActiveProtectionService) are documented as cloud-aware. For commercial tenants, substitute the explicit .us domain suffixes in the remaining rules with .com equivalents; the tag-based rules do not change.

FQDN tag content gaps in GCC High: pair tags with explicit fallbacks

Service tags (IP-based) are reliably cloud-aware and resolve to sovereign IP ranges automatically. FQDN tags (FQDN-based) do not always carry their full sovereign FQDN list. The Azure Firewall FQDN tags overview documents that customers cannot inspect or modify tag contents: Microsoft hand-curates the FQDN list per tag, and sovereign endpoints sometimes lag or are missing entirely. Observed in deployments: *.wvd.azure.us (the GCC High AVD broker domain) is documented under the WindowsVirtualDesktop service tag but is not reliably present in the WindowsVirtualDesktop FQDN tag: traffic falls through to the deny-all even when the rule is correctly configured.

The pattern in this appendix is to pair every FQDN tag with explicit sovereign FQDNs as a fallback. The tag still buys forward compatibility for what Microsoft does maintain in it; the explicit fallback closes the gap. If you find another denied FQDN that should be covered by a tag, add it explicitly to the corresponding rule rather than assuming the tag is wrong.


Rule Structure and Priority Model

Rules are organized into application rule collections and network rule collections. Within each collection, rules are evaluated top-to-bottom. Collections are evaluated lowest-priority-number first. The deny-all catch-all at priority 4096 terminates any traffic not matched by an explicit allow.

Application rules and network rules have separate priority namespaces

In the Azure Firewall UI, Application rule collections and Network rule collections are configured in separate tabs with independent priority numbering. A network rule at Priority 200 and an application rule at Priority 200 do not conflict: they are evaluated independently.

Application rule collections (FQDN-based, for TCP/HTTP/HTTPS traffic):

PriorityCollectionScope
100AVD-Control-PlaneAVD platform (tag) + deployment-specific storage, ServiceBus, Key Vault, ARM, Graph, agent hub
110Cert-ServicesThird-party CRL/OCSP (Entrust, DigiCert, GlobalSign)
120M365Microsoft 365 (Office365 tag) and Intune (MicrosoftIntune tag)
130Windows-ManagementWindows Update, diagnostics, activation, browser, NCSI, SmartScreen, CRL/OCSP
140Defender-For-EndpointMDE sensor communication (MAPS tag + portal)
150Third-Party-SecurityProofpoint URL Defense, PhishAlarm
160Azure-BackupRecovery Services Vault control plane and queue-storage backend (AzureBackup tag + explicit sovereign FQDNs)
165Operations-DocumentationDeployment runbook and operational documentation (docs.mindline.com, learn.microsoft.com)
200–299Customer-*Customer-specific application rules (see template)
4096Deny-All-LogCatch-all deny with logging

Network rule collections (IP/port-based, evaluated before application rules for matching traffic):

PriorityCollectionScope
200Essential-PortsDNS, IMDS, Azure health probe, NTP
210Teams-MediaTeams audio/video UDP ports
220Azure-ServicesEntra ID, Azure Monitor, KMS activation via service tags

Application Rule Collections

Priority 100: AVD-Control-Plane

Rule NameProtocolTargetPurpose
AVD-PlatformHTTPS:443fqdnTag: WindowsVirtualDesktop plus explicit FQDNs: *.wvd.azure.us, ecs.office.com, *.attest.azure.usAVD gateway, broker, attestation, side-by-side stack, connection center, and Azure Attestation. *.wvd.azure.us covers the GCC High broker domain that the FQDN tag does not reliably carry (see the FQDN-tag-gap warning above). ecs.office.com is the AVD connection center: Microsoft's endpoint reference documents it without a service tag, so it must be listed explicitly. *.attest.azure.us covers Azure Attestation regional endpoints (sharedugv.ugv.attest.azure.us, shareduga.uga.attest.azure.us, etc.) used by Trusted Launch VMs at boot to validate TPM and Secure Boot state. The AzureAttestation service tag exists but is IP-based (NSG / network rules only); for application-rule FQDN coverage the wildcard is required.
AVD-DeploymentHTTPS:443*.blob.core.usgovcloudapi.net, *.table.core.usgovcloudapi.net, *.servicebus.usgovcloudapi.net, *.vault.usgovcloudapi.net, management.usgovcloudapi.net, pasff.usgovcloudapi.net, graph.microsoft.us, agenthubprod.azureedge.us, fs.microsoft.com, portal.azure.us, *.portal.azure.us, *.hosting.portal.azure.us, *.azureportal.usgovcloudapi.net, *.applicationinsights.us, *.loganalytics.us, *.msidentity.us, *.usgovtrafficmanager.net, *.windowsazure.us, *.s-microsoft.comStorage, ServiceBus, Key Vault, ARM, Graph, agent hub, and Windows config service: deployment-specific endpoints not covered by the tag. Azure Government portal: two distinct namespaces: the user-facing landing URL (portal.azure.us, *.portal.azure.us, *.hosting.portal.azure.us) is what administrators type into the address bar, while the portal extension hosting infrastructure (*.azureportal.usgovcloudapi.net) is where individual blades (including the Microsoft Entra admin center's IAM, Conditional Access, and Application blades) actually load their JavaScript, React framework (reactblade.azureportal.usgovcloudapi.net), and per-blade sandboxed iframes (sandbox-N.reactblade.azureportal.usgovcloudapi.net). Both wildcards are required: missing the second namespace makes the portal landing page load while every blade inside fails with a generic loading error. Azure portal resource-blade dependencies are pulled in from the Azure portal allowlist (US Government Cloud): specifically *.applicationinsights.us (Application Insights blade), *.loganalytics.us (Log Analytics / KQL queries), *.msidentity.us (identity-platform-specific blade content), *.usgovtrafficmanager.net (Traffic Manager blade), *.windowsazure.us (legacy Azure namespace still used by older blade extensions), and *.s-microsoft.com (Azure Marketplace storefront). These wildcards are documented by Microsoft as required for full Azure portal admin functionality and are required only when AVD users perform Azure resource administration from inside the session. Specific resource blades pull additional endpoints already covered by other rules: Storage Explorer uses *.blob.core.usgovcloudapi.net (here), Key Vault blade uses *.vault.usgovcloudapi.net (here), and the AAD admin blade uses Graph endpoints in the M365 collection.
AVD-Deployment-HttpHTTP:80ctldl.windowsupdate.com, fs.microsoft.comCertificate trust list and Windows config service: HTTP-only access path (the HTTPS access path is covered by AVD-Deployment)

Priority 110: Cert-Services

Rule NameProtocolTarget FQDNsPurpose
Cert-ServicesHTTPS:443, HTTP:80*.entrust.net, *.digicert.com, *.globalsign.comCRL/OCSP for third-party certificate authorities

Priority 120: M365

Rule NameProtocolTargetPurpose
Office365HTTPS:443fqdnTag: Office365 plus the explicit fallback list aligned to the GCC High M365 Common and Office Online endpoint table: *.edge.skype.com, www.office.com, www.microsoft365.com, *.office365.us, *.gov.online.office365.us, *.usgovcloud.microsoft, *.usgovcloud-static.microsoft, *.usgovcloud-usercontent.microsoft, *.auth.microsoft.us, *.gov.us.microsoftonline.com, login.microsoftonline.us, graph.microsoftazure.us, entra.microsoft.us, *.entra.microsoft.us, entra.microsoft.com, *.entra.microsoft.com, login.microsoftonline.com, login-us.microsoftonline.com, loginex.microsoftonline.com, login.windows.net, graph.windows.net, clientconfig.microsoftonline-p.net, *.microsoftonline-p.com, *.msauth.net, *.msauthimages.us, *.msftauth.net, *.msftauthimages.us, *.cdn.office.net, officehome.msocdn.us, lpcres.delve.office.com, has.spserv.microsoft.com, officeclient.microsoft.com, config.svc.cloud.microsoft, *.officeapps.live.com, *.office.delivery.microsoft.com, officecdn.microsoft.com, officecdn.microsoft.com.edgesuite.net, office15client.microsoft.com, officepreviewredir.microsoft.com, officeredir.microsoft.com, r.office.microsoft.com, insertmedia.bing.office.net, to-do.microsoft.com, wcpstatic.microsoft.com, account.activedirectory.windowsazure.us, gov.teams.microsoft.us, *.gov.teams.microsoft.us, statics.teams.microsoft.com, *.nel.measure.office.net, attachments.office365-net.us, oneclient.sfx.ms, g.live.com, admin.onedrive.us, *.svc.ms, *.aadrm.us, *.informationprotection.azure.us, admin.microsoft.com, outlook.office365.comExchange, SharePoint, Teams signaling, M365 portal, Office Online, Office desktop client activation and delivery, Microsoft Entra auth UI and branding, Office Home, Delve, Outlook hosted add-ins, My Apps, and Entra ID account management. The fallback list groups roughly as: the GCC High *.office365.us namespace (covers portal.office365.us, www.office365.us, outlook.office365.us, OSI, Loki, Tasks via wildcard); the new Microsoft 365 Unified Domains namespace (*.usgovcloud.microsoft, *.usgovcloud-static.microsoft, *.usgovcloud-usercontent.microsoft) into which Microsoft is migrating SaaS UI experiences such as the M365 portal and My Apps; GCC High native auth and Graph (*.auth.microsoft.us, *.gov.us.microsoftonline.com, plus the explicit login.microsoftonline.us central token endpoint and graph.microsoftazure.us AAD Graph in case the Office365 fqdnTag's coverage drifts); the Microsoft Entra admin center for both sovereign and commercial namespaces (entra.microsoft.us, *.entra.microsoft.us, entra.microsoft.com, *.entra.microsoft.com): Microsoft documents both wildcards as required for GCC High in the Entra ID FAQ because the admin center's MSAL bootstrap follows the same instance-discovery pattern as login.microsoftonline.com; the Entra auth UI CDN family (*.msauth.net, *.msauthimages.us, *.msftauth.net, *.msftauthimages.us) plus the legacy auth UI shell wildcard (*.microsoftonline-p.com, which consolidates secure.aadcdn.microsoftonline-p.com, login.microsoftonline-p.com, and nexus.microsoftonline-p.com into one entry) which the Office365 FQDN tag claims to carry but in practice does not reliably resolve sovereign-cloud variants; the cross-cloud auth and instance-discovery endpoints required by MSAL bootstrap and OneAuth/WAM (login.microsoftonline.com, login-us.microsoftonline.com, loginex.microsoftonline.com, login.windows.net, graph.windows.net, clientconfig.microsoftonline-p.net): see the Why login.microsoftonline.com (commercial) is required in GCC High info note immediately below this table for the rationale and Microsoft source citations; the M365 UI shell, Office Home, and Delve (*.cdn.office.net, officehome.msocdn.us, lpcres.delve.office.com); Office Online and document cache (*.officeapps.live.com, *.office.delivery.microsoft.com); Office desktop client config and redirects (officeclient.microsoft.com, office15client.microsoft.com, officeredir.microsoft.com, officepreviewredir.microsoft.com, r.office.microsoft.com, officecdn.microsoft.com, officecdn.microsoft.com.edgesuite.net); Office "Insert Media" (insertmedia.bing.office.net); the Outlook hosted add-in service (has.spserv.microsoft.com); Web Conferencing Provider static for Outlook→Teams meeting join (wcpstatic.microsoft.com); Microsoft To Do (to-do.microsoft.com); the unified Microsoft Cloud config endpoint (config.svc.cloud.microsoft); Teams/Skype configuration (*.edge.skype.com); cross-cloud redirect targets that GCC High inherits (www.office.com, www.microsoft365.com); the My Apps / Entra ID account portal backend API (account.activedirectory.windowsazure.us); the GCC High Microsoft Teams namespace (gov.teams.microsoft.us, *.gov.teams.microsoft.us, statics.teams.microsoft.com): required for Teams real-time signaling and the Trouter routing service (e.g., go.trouter.gov.teams.microsoft.us), documented as AllowRequired in GCC High Microsoft Teams row 31, with statics.teams.microsoft.com (Row 21) covering the Teams web client static asset CDN; the M365 Network Error Logging endpoint (*.nel.measure.office.net): covering m365cdn.nel.measure.office.net and officehub.nel.measure.office.net, which Office and M365 web clients use for browser-side network error reporting; the Exchange attachment service (attachments.office365-net.us): note this is a different TLD from *.office365.us so the wildcard does not catch it; OneDrive sync client endpoints (oneclient.sfx.ms, g.live.com, admin.onedrive.us), documented as DefaultRequired in GCC High SharePoint/OneDrive Row 10 and reinforced in OneDrive Sync Release Notes (suppressing g.live.com will silently break OneDrive sync; allow-list, do not block); SharePoint sync infrastructure (*.svc.ms, Row 20); and Azure Information Protection / sensitivity labels (*.aadrm.us, *.informationprotection.azure.us, Row 30), required for any tenant using AIP / unified labeling / Microsoft Purview Information Protection; and the commercial M365 admin center and Outlook bootstrap endpoints (admin.microsoft.com, outlook.office365.com) which OneAuth/WAM probes during the same instance-discovery flow as login.microsoftonline.com: when a GCC High user opens the M365 admin center or starts an Outlook desktop session, the client first reaches the commercial endpoint to learn the tenant's home cloud, gets the sovereign-cloud redirect, and completes the actual session at admin.microsoft.us / outlook.office365.us. Without these two entries, the M365 admin center loads blank and Outlook desktop sign-in stalls before reaching the sovereign endpoint. Both carry the #disable-next-line no-hardcoded-env-urls Bicep directive as intentional CAB evidence. The wildcard *.office365.us is preferred over enumerating sovereign subdomains so future GCC High *.office365.us rollouts are covered automatically.
IntuneHTTPS:443fqdnTag: MicrosoftIntune plus explicit FQDNs: *.manage.microsoft.us, intune.microsoft.us, discovery.dm.microsoft.us, imeswdsc-afd-pri.manage.microsoft.comIntune MDM enrollment, device-management discovery, policy delivery, and the Microsoft Intune admin center. The explicit *.manage.microsoft.us covers the Intune service endpoints (manage.microsoft.us, r.manage.microsoft.us, etc.) documented by Microsoft; intune.microsoft.us is the GCC High Intune admin portal URL (documented as a US Government customer-designated endpoint), required when administrators open the Intune admin center from inside an AVD session. discovery.dm.microsoft.us is the sovereign MDM device-management discovery endpoint: clients hit it during the enrollment handshake and during subsequent MDM check-ins; not reliably carried by the FQDN tag in GCC High. imeswdsc-afd-pri.manage.microsoft.com is the Intune Management Extension Win32 app delivery service (IME Software Distribution Service via Azure Front Door): the FQDN is intentionally .com because Microsoft hosts Win32 content delivery as a single global service with no sovereign equivalent; without this entry, Win32 app deployments fail silently and the IME log shows HTTP 0 connection-refused errors that are easy to misdiagnose as content-URL problems rather than a firewall block. Carries the #disable-next-line no-hardcoded-env-urls Bicep directive as intentional cross-cloud CAB evidence. The MicrosoftIntune FQDN tag does not reliably carry any of these in GCC High.
Entra-RegistrationHTTPS:443enterpriseregistration.windows.net, enterpriseregistration.microsoftonline.usEntra ID device registration endpoint. Required at first boot for Entra-joined and hybrid-joined session hosts to register; not carried by the Office365 or MicrosoftIntune FQDN tags. Both variants are listed: .windows.net is the legacy commercial cross-cloud namespace that current desktop clients still target, and .microsoftonline.us is the GCC High sovereign ADRS endpoint documented by Microsoft and required by Intune partner service endpoints. Different builds of the device-registration client target different endpoints; allowing both eliminates the version-dependency.
Why commercial endpoints appear in a GCC High allow list

The Office365 rule explicitly allows several commercial-cloud endpoints (login.microsoftonline.com, login.windows.net, graph.windows.net, *.microsoftonline-p.com, the legacy login-us.microsoftonline.com, and the Microsoft Entra admin center wildcards entra.microsoft.com / *.entra.microsoft.com) even though the tenant authenticates against login.microsoftonline.us and administrators land at entra.microsoft.us. This is not a leak; Microsoft documents these as required for GCC High in two places. The auth endpoints are listed in Microsoft 365 Common and Office Online row 14 (and the same row appears in the DoD endpoint list). The Entra admin center wildcards are listed in the Microsoft Entra ID FAQ — How can I allow Microsoft Entra admin center URLs on my firewall or proxy server?, which explicitly enumerates *.entra.microsoft.com, *.entra.microsoft.us, and *.entra.microsoftonline.cn together, meaning Microsoft considers all three TLD variants reachable from any cloud's admin center.

Why MSAL probes the commercial endpoint: MSAL.js, MSAL.NET, and OneAuth/WAM start every auth flow with an instance discovery call to login.microsoftonline.com/common/discovery/instance to determine which sovereign cloud the tenant lives in. The discovery response identifies the tenant as sovereign and redirects the actual sign-in to login.microsoftonline.us, but the discovery probe itself targets the commercial endpoint. Without firewall reachability, the MSAL bootstrap stalls and downstream pages (myapps.microsoft.us, the Entra admin center at entra.microsoft.us, the M365 portal, anything embedding MSAL.js) load blank. The Entra admin center follows the same pattern: a probe to entra.microsoft.com precedes the redirect to entra.microsoft.us. See National clouds — authentication endpoints for the cloud-discovery model.

Sign-in via the commercial endpoint still fails as designed: Reaching login.microsoftonline.com over the network does not enable sign-in there. Entra enforces sovereign authentication for sovereign tenants and returns AADSTS900439 — USGClientNotSupportedOnPublicEndpoint if a sovereign client tries to sign in via the public endpoint. Allowing the FQDN at the firewall lets the discovery probe complete; it does not let users sign in via the commercial endpoint.

For CAB review: This entry exists to support the documented MSAL/OneAuth instance-discovery probe required by Microsoft's published GCC High endpoint list. It supports authentication availability, not commercial authentication. The Bicep #disable-next-line no-hardcoded-env-urls directive on these lines suppresses the standard Bicep linter warning for hardcoded environment URLs precisely because this exception is intentional and source-cited.

Add your tenant's SharePoint Online and OneDrive domains explicitly

The Office365 FQDN tag is documented as covering SharePoint Online, but in GCC High deployments tenant-specific subdomains commonly fall through to the deny-all, the same FQDN-tag-gap pattern called out at the top of this appendix. For each tenant whose users connect from this AVD environment, add <tenant>.sharepoint.us (SharePoint sites) and <tenant>-my.sharepoint.us (OneDrive for Business) as explicit fallback FQDNs, either appended to the Office365 rule's targetFqdns, or as a per-customer collection at Priority 200+ following the Customer Application Rule Template. Without the -my variant, OneDrive for Business sync fails silently while the SharePoint site itself appears to load.

Teams media traffic goes through network rules, not application rules

Teams audio and video (real-time media) use UDP ports 3478–3481 and 49152–53247 (ephemeral). These cannot be matched by FQDN-based application rules because UDP traffic is evaluated by Azure Firewall network rules only. See Network Rules: Teams-Media below.


Priority 130: Windows-Management

Rule NameProtocolTargetPurpose
WindowsUpdateHTTPS:443, HTTP:80fqdnTag: WindowsUpdateWindows Update, Delivery Optimization, WSUS catalog, and App metadata
WindowsDiagnosticsHTTPS:443fqdnTag: WindowsDiagnostics plus explicit FQDNs: *.events.data.microsoft.com, *.wosc.services.microsoft.com, *.pipe.aria.microsoft.comWindows telemetry, Connected User Experiences, and OneSettings (Windows OS configuration delivery). The explicit *.events.data.microsoft.com covers versioned telemetry subdomains (e.g., v20.events.data.microsoft.com); the explicit *.wosc.services.microsoft.com covers Microsoft's newer OneSettings namespace (prod.client.wosc...) under the unified services.microsoft.com umbrella, which the tag's curated list has not yet picked up; the explicit *.pipe.aria.microsoft.com wildcard covers the Aria telemetry pipeline at any subdomain: both the browser-side variant (browser.pipe.aria.microsoft.com) used by Edge and Office browser components, and the M365 Common variant (tb.pipe.aria.microsoft.com) documented in GCC High M365 Common row 32. All three entries are forward-compatible with future subdomain rollouts.
WNSHTTPS:443*.wns.windows.comWindows Push Notification Service: toast/tile notifications, Microsoft Store update push, MDM notification channel. Not currently covered by any FQDN tag.
Store-Licensing-ActivationHTTPS:443, HTTP:80*.sls.microsoft.com, licensing.mp.microsoft.com, displaycatalog.mp.microsoft.com, titles.gcch.mos.svc.usgovcloud.microsoft, services.autopatch.microsoft.us, storeedgefd.dsx.mp.microsoft.com, adl.windows.comWindows/Office activation, Store catalog and delivery (storeedgefd.dsx.mp.microsoft.com is the Microsoft Store Edge front door used to fetch Store apps and metadata), Autopatch control plane, and Windows Update App Delivery Layer (adl.windows.com)
PowerShell-GalleryHTTPS:443www.powershellgallery.com, *.powershellgallery.com, cdn.powershellgallery.com, cdn.oneget.org, go.microsoft.com, aka.msPowerShell Gallery: the registry that Install-Module, Find-Module, Update-Module, and Save-Module hit by default. Discovery and download are different hosts, and that distinction is the whole trap. www.powershellgallery.com serves the NuGet API and metadata; the actual .nupkg comes from cdn.powershellgallery.com, which the API redirects to. Allow only the first and Install-Module resolves a specific package version, then fails with Source Location '...' is not valid and Package '<name>' failed to download. That reads as a broken or untrusted repository rather than a firewall block, which sends you to Set-PSRepository instead of the firewall log. The psg-prod-*.azureedge.net and onegetcdn.azureedge.net endpoints are retired. Microsoft states plainly that "the old endpoints that ended with azureedge.net are no longer supported" (network access to the PowerShell Gallery), yet they still appear in other current Microsoft pages such as the SAP deployment planning guide; allowlists built from those pages will fail. cdn.oneget.org covers the OneGet / PackageManagement provider catalog. go.microsoft.com and aka.ms are the redirection services Microsoft lists as required. Not covered by any FQDN tag. Note the Gallery also requires TLS 1.2+, which Windows PowerShell 5.1 does not always negotiate: rule out [Net.ServicePointManager]::SecurityProtocol before blaming the firewall.
Edge-BrowserHTTPS:443, HTTP:80edge.microsoft.com, msedge.api.cdp.microsoft.comEdge update and configuration. The HTTP:80 path is required because Edge's update channel falls back to plain HTTP for differential download and CRX delivery when HTTPS metadata is already cached; without it the cached path emits HTTP requests that fall through to the deny-all.
NCSIHTTP:80www.msftconnecttest.com, windows.msn.com, windows.msn.cnNetwork Connectivity Status Indicator
SmartScreen-WatsonHTTPS:443*.smartscreen.microsoft.com, *.smartscreen-prod.microsoft.com, checkappexec.microsoft.com, *.urs.microsoft.com, *.watson.microsoft.com, unitedstates1.ss.wd.microsoft.usSmartScreen URL reputation + Watson error reporting. checkappexec.microsoft.com is the application-reputation endpoint, apex only: Microsoft documents it as *.checkappexec.microsoft.com, but the call is to the bare domain and an Azure Firewall wildcard does not match an apex. Without it, running a downloaded .exe shows "SmartScreen can't be reached right now" with a Run button, so the control fails open rather than blocking. unitedstates1.ss.wd.microsoft.us is the GCC High SmartScreen explicit endpoint documented in MDE Standard Connectivity URLs - US Government; the commercial wildcards do not catch *.wd.microsoft.us.
CRL-OCSPHTTP:80, HTTPS:443ocsp.msocsp.com, mscrl.microsoft.com, oneocsp.microsoft.com, crl.microsoft.com, crl2.microsoft.com, *.pki.core.windows.net, www.microsoft.com, go.microsoft.comMicrosoft certificate revocation list and OCSP distribution
Azure-CLI-InstallHTTPS:443azcliprod.blob.core.windows.netThe host Microsoft publishes the Azure CLI MSI and ZIP packages to, via versioned URLs (install doc, proxy section).
Bicep-CLIHTTPS:443downloads.bicep.azure.comWhere az bicep install and az deployment ... --template-file <file>.bicep fetch the Bicep CLI. This host is not documented by Microsoft. The air-gapped install guidance still directs you to GitHub releases, and downloads.bicep.azure.com appears nowhere on Microsoft Learn, so a firewall built from the documentation blocks it. Field-observed on Azure CLI 2.89.0, which calls downloads.bicep.azure.com/releases/latest. Allowing this one FQDN means Bicep deployments work natively from a session host, with no GitHub rule and no hand-staged bicep.exe. The failure signature is a TLS error, not an HTTP one: SSLEOFError ... UNEXPECTED_EOF_WHILE_READING, which is the firewall dropping the connection at SNI and reads like a broken download rather than a policy block.

Azure CLI on a session host

The CLI is available on any session host, and authorization to do anything with it is an Entra RBAC and PIM concern, not a firewall concern. Reaching a management endpoint is not permission to act on it.

Restricting where the CLI can be downloaded would not constitute a boundary in any case: management.usgovcloudapi.net, portal.azure.us, and graph.microsoft.us are allowed to every session-host subnet by the AVD-Deployment rule, and the PowerShell Gallery by the rule above, so any user can reach Azure management through the browser or Install-Module Az without touching this FQDN. The firewall is not an identity boundary and should not be architected as one.

Install a pinned version (version URLs per the install doc). Run PowerShell as administrator:

$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri https://azcliprod.blob.core.windows.net/msi/azure-cli-<version>-x64.msi -OutFile .\AzureCLI.msi
Start-Process msiexec.exe -Wait -ArgumentList '/I', 'AzureCLI.msi', '/quiet'
Remove-Item .\AzureCLI.msi

Close and reopen the terminal afterwards. Microsoft lists an unset PATH as the most common install failure, and the cause is always a shell that was open before the install.

Pinning is a policy choice here, not a firewall constraint. Microsoft's proxy guidance for the MSI requires HTTPS to exactly https://aka.ms/ and https://azcliprod.blob.core.windows.net/, and both are now allowed from every session-host subnet: aka.ms was added to the PowerShell-Gallery rule as a required redirection service. So https://aka.ms/installazurecliwindowsx64 resolves the latest 64-bit MSI and works from inside the enclave. Earlier revisions of this appendix said the aka.ms shortlink was deliberately blocked; that is no longer true.

Pin anyway on a CUI fleet, because change control wants a known version rather than whatever "latest" resolves to on the day, and because a pinned URL is reproducible evidence. That is a policy position you can revisit, not a wall.

The same nuance applies to az upgrade, which was previously ruled out because it reaches aka.ms. It may now work; whether it touches endpoints beyond those two hosts is unverified, confirm before relying on it. Reinstalling a newer pinned MSI remains the deterministic path.

No local admin? The MSI needs elevation, but Microsoft publishes a ZIP distribution specifically for that case (currently in preview, 64-bit only, from version 2.57.0). Unzip it and call <folder>\bin\az.cmd, or add that bin directory to your user PATH:

Invoke-WebRequest -Uri https://azcliprod.blob.core.windows.net/zip/azure-cli-<version>-x64.zip -OutFile .\azcli.zip
Expand-Archive .\azcli.zip -DestinationPath $HOME\azcli

Expect winget install Microsoft.AzureCLI to fail behind this firewall, by design. WinGet pulls its package index from its own CDN, which is not allowed: opening it would enable installing any WinGet package from inside the enclave, a far broader surface than one binary from a Microsoft-owned host. The MSI or ZIP above is the supported path.

Acquiring GitHub-distributed admin tools

Some admin tools are distributed only from GitHub releases, the Microsoft Win32 Content Prep Tool (IntuneWinAppUtil.exe) being the common one. GitHub is not a standing rule in this template because it is too large a surface for a CUI enclave.

The Bicep CLI is not in this category: it comes from downloads.bicep.azure.com, allowed by the Bicep-CLI rule above, so az bicep install works without opening GitHub at all.

The supported pattern is a time-boxed, CAB-approved window, during which you fetch everything you need at once, verify it, then close the rule.

FQDNs required (field-observed while browsing and downloading from GitHub):

FQDNPurpose
github.com, *.github.comThe site and the release pages. Both apex and wildcard: the wildcard does not match the apex
*.githubusercontent.comRelease asset downloads. GitHub redirects /releases/download/ to objects.githubusercontent.com, so without this the page loads and the download fails
github.githubassets.comStatic assets for the web UI
images.ctfassets.netContentful CDN used by GitHub's marketing pages. Needed only for browsing; omit if you script the downloads

Procedure:

  1. Define the temporary rule.

  2. Deploy the policy and fetch the release binaries:

    Invoke-WebRequest -Uri https://github.com/Azure/bicep/releases/latest/download/bicep-win-x64.exe -OutFile .\bicep.exe
  3. Verify each binary before use, which is the point of doing this deliberately rather than ad hoc:

    Get-AuthenticodeSignature .\bicep.exe | Format-List Status, SignerCertificate
    Unblock-File .\bicep.exe

    Unblock-File clears the Mark of the Web so SmartScreen does not prompt on first run.

  4. Remove the rule and redeploy.

  5. Package anything recurring for Intune rather than repeating this. A Win32 app assigned to the admin group survives host rebuilds, arrives through an audited channel, and is tagged trusted by the managed installer under App Control. Repeating the firewall window for every tool update turns a defensible one-off into a pattern an assessor will question.

Do the packaging on an in-scope device, meaning an admin session host rather than a personal workstation. The machine that decides what software reaches CUI assets is a Security Protection Asset (clean source principle; see also Chapter 1-2 asset categories).


Priority 140: Defender-For-Endpoint

Rule NameProtocolTargetPurpose
MAPSHTTPS:443fqdnTag: MicrosoftActiveProtectionServiceCloud-delivered protection (block-at-first-sight, reputation, sample submission)
Security-Compliance-PortalsHTTPS:443*.security.microsoft.us, security.microsoft.us, compliance.microsoft.us, purview.microsoft.us, winatp-gw-usgt.microsoft.com, unitedstates1.cp.wd.microsoft.us, unitedstates1.x.cp.wd.microsoft.us, *.securitycenter.microsoft.us, securitycenter.microsoft.us, us4-v20.events.data.microsoft.com, *.securitycenter.windows.us, securitycenter.windows.usMicrosoft 365 security and compliance admin portals plus MDE GCC High service endpoints. securitycenter.microsoft.us is a different namespace from security.microsoft.us and is easy to conflate: it carries the GCC High Defender for Endpoint API (api-gov.securitycenter.microsoft.us) and is documented for GCC High. us4-v20.events.data.microsoft.com is the EDR cyber data channel, documented Required for GCC High in the same reference. *.securitycenter.windows.us is field-observed and not in Microsoft's published lists: a session host was denied mgmt-mdgw-ff.securitycenter.windows.us (note .windows.us, not the documented .microsoft.us). The wildcard is used because the instance prefix appears ring-specific. Re-check this entry each release and remove it if Microsoft never documents the namespace and no further denies appear. Sample-submission and onboarding-package blobs are already covered by *.blob.core.usgovcloudapi.net in the AVD-Deployment rule. *.security.microsoft.us / security.microsoft.us: Microsoft Defender XDR portal (Defender for Endpoint, Defender for Office 365, Defender for Identity, Defender for Cloud Apps unified surface). compliance.microsoft.us, purview.microsoft.us: Microsoft Purview portal: DLP, Information Protection, eDiscovery, audit; documented as AllowRequired in GCC High M365 Common Row 26. winatp-gw-usgt.microsoft.com: the Microsoft Defender for Endpoint GCC High Command-and-Control gateway, documented in MDE Standard Connectivity URLs - US Government. Note: earlier versions of this appendix listed *.winatp-gw-usw.microsoft.com; that pattern is not in current Microsoft documentation and is replaced by the explicit winatp-gw-usgt.microsoft.com GCC High C2 endpoint. unitedstates1.cp.wd.microsoft.us and unitedstates1.x.cp.wd.microsoft.us: the GCC High MAPS / cloud-delivered protection / security intelligence update endpoints: these are not reliably carried by the MicrosoftActiveProtectionService FQDN tag in GCC High and are explicitly listed by Microsoft in the same MDE doc.

Priority 150: Third-Party-Security

Rule NameProtocolTarget FQDNsPurpose
ProofpointHTTPS:443, HTTP:80urldefense.us, *.urldefense.us, addin-us.securityeducation.comProofpoint URL Defense rewrite/click-through, PhishAlarm reporting add-in

Priority 160: Azure-Backup

Outbound rules for Azure VM backup from session hosts to the Recovery Services Vault. Only required when Step 13 of the deployment runbook is followed with the public-access path (default). If the deployment uses a private endpoint instead, this rule collection is unused: backup traffic stays inside the VNet.

Rule NameProtocolTargetPurpose
AzureBackupHTTPS:443fqdnTag: AzureBackup plus explicit FQDNs: *.backup.windowsazure.us, *.queue.core.usgovcloudapi.netAzure VM backup outbound to the Recovery Services Vault (*.backup.windowsazure.us) and the storage-account queue backend used for backup orchestration (*.queue.core.usgovcloudapi.net). The AzureBackup FQDN tag exists but, per the FQDN-tag-gap warning, is not reliably populated with sovereign FQDNs in GCC High: pair the tag with the explicit fallbacks. The blob backend (*.blob.core.usgovcloudapi.net) and ARM endpoint (management.usgovcloudapi.net) are already covered by the AVD-Deployment rule and do not need to be repeated here; auth via login.microsoftonline.us is already covered by the Office365 rule.
Skip this collection if the vault uses a private endpoint

The private-endpoint alternative described in Step 13 routes backup traffic over a private IP inside the AVD VNet, so the firewall is not in the data path and these FQDN rules are never matched. The collection can be deleted from the Bicep template if you are certain you will not switch back to public access.

Priority 165: Operations-Documentation

Rule NameProtocolTarget FQDNsPurpose
Deployment-RunbookHTTPS:443docs.mindline.com, *.algolia.net, *.algolianet.comThe deployment runbook and operational documentation for this environment, reachable from inside the enclave so administrators and users can follow procedures without leaving the session. Site search is served by Algolia DocSearch, an external service. Earlier revisions excluded it on the reasoning that browsing was sufficient; that was reversed after a session host was observed being denied Algolia hosts while an operator was working the runbook. Browsing without search is the slower half of following a procedure, and the search box fails silently rather than reporting a network error. Both wildcards are required, and they sit on different apexes. A single search produced denies for <appid>-dsn.algolia.net plus <appid>-1, <appid>-2, and <appid>-3 on .algolianet.com: the client resolves the primary host, then retries across numbered failover hosts under the second domain. Allowing only *.algolia.net leaves search broken as soon as a retry occurs, which is the common case from a high-latency enclave.
Microsoft-LearnHTTPS:443learn.microsoft.comMicrosoft Learn is the primary citation target of the runbook and appendices; operators following procedures inside the enclave click through to it constantly. Apex only: articles and images render fully from the apex. Embedded videos (learn-video.azurefd.net) are deliberately not allowed; they are not needed to read documentation. Note aka.ms is allowed, in the Windows-Management PowerShell-Gallery rule where Microsoft lists it as a required redirection service, so Learn shortlinks resolve; it was blocked when this collection was first written.

Priority 170: Client-Tenant-Endpoints

Tenant-specific FQDNs (SharePoint Online, OneDrive, and any other per-deployment hostnames) supplied through the clientTenantFqdns parameter rather than hard-coded in the template. The rule collection is generated only when the parameter is non-empty: by default the template ships without this collection at all, and adding a tenant's hostnames is an edit to the parameter file, not to avd-firewall.bicep. See Tenant-Specific Endpoints (Parameter File) for the deployment pattern.


Network Rule Collections

Priority 200: Essential-Ports

Traffic that cannot be expressed as FQDNs (IP-based or protocol-based infrastructure requirements).

Rule NameProtocolSourceDestinationDestination PortPurpose
DNSUDP, TCPSession host subnetAny53DNS resolution (use Azure DNS or your DNS resolver IP)
IMDSTCPSession host subnet169.254.169.25480Azure Instance Metadata Service: required for VM identity tokens
Azure-HealthProbeTCPSession host subnet168.63.129.1680Azure load balancer health probe: required for VM reachability
NTPUDPSession host subnetAny123NTP time sync
IMDS and Azure health probe must be allowed

169.254.169.254 (IMDS) and 168.63.129.16 (health probe) are link-local addresses that Azure uses for internal platform communication. If your UDR sends all traffic to the firewall and these destinations are blocked by the deny-all rule, VMs will lose their managed identity tokens and health probe responses, causing enrollment failures, Intune policy application errors, and VM unavailability in the load balancer.

Priority 210: Teams-Media

Teams real-time audio and video require UDP. Azure Firewall cannot inspect UDP by FQDN: these ports must be opened by IP range or service tag.

Rule NameProtocolSourceDestinationDestination PortsPurpose
Teams-STUN-TURNUDPSession host subnetAzureCloud.usgovvirginia, AzureCloud.usgovariz3478–3481STUN/TURN for Teams media relay
Teams-Media-EphemeralUDPSession host subnetAzureCloud49152–53247Teams audio/video media streams
Why such a wide port range?

Teams uses ephemeral UDP ports (49152–53247) for peer-to-peer and relay media. The Microsoft transport relay selects from this range based on session negotiation. Narrowing the range causes intermittent audio/video failures that are difficult to diagnose because HTTPS signaling continues to work.

Priority 220: Azure-Services

Service-tag rules for Azure platform services where IP-range coverage is more reliable than FQDN matching, and for KMS activation's non-HTTPS port.

Rule NameProtocolSourceDestination (Service Tag or IP)Destination PortsPurpose
AzureActiveDirectoryTCPSession host subnetAzureActiveDirectory443Entra ID IP range coverage
AzureMonitorTCPSession host subnetAzureMonitor443Log Analytics, diagnostics, Azure Monitor
KMS-ActivationTCPSession host subnet23.97.0.13/32, 52.126.105.2/321688Windows KMS license activation. Explicit IPs, not a service tag: the Azure US Gov KMS endpoints (kms / azkms .core.usgovcloudapi.net) are published under service tag Internet, not AzureCloud, so an AzureCloud-scoped rule silently misses them and activation fails with 0xC004F074. Microsoft documents these explicit IPs for forced-tunneling scenarios.

Session-Host Subnets (Parameter File)

Every Allow rule in avd-firewall.bicep is scoped to a sourceAddresses list driven by the avdSubnetAddressSpace parameter. The parameter is an array: every entry in the array becomes a permitted source CIDR on every rule. A request whose source IP doesn't match any entry falls through the Allow collection and hits the Deny-All-Log rule at Priority 4096, even when the destination FQDN is otherwise allowed.

This matters when you add a host pool. The Multi-Pool Variant of the deployment runbook places each host pool in its own subnet (see Step 3 of Appendix D.1 § Multi-Pool Variant). Each new subnet must be added to avdSubnetAddressSpace and the firewall policy redeployed before the new pool's session hosts can reach Microsoft endpoints. Otherwise the symptom is a flood of denies for FQDNs that are visibly present in the Allow rules, including the AVD DSC artifact endpoint (wvdportalstorageblob.blob.core.usgovcloudapi.net, covered by the *.blob.core.usgovcloudapi.net wildcard in Priority 100: AVD-Control-Plane). The DSC extension fails with "The underlying connection was closed" after 17 retry attempts; the firewall logs show the deny against the deny-all-log collection rather than the named allow rule.

Parameter file template

using './avd-firewall.bicep'

// Session-host subnet CIDR blocks — one entry per host pool.
// Verify against the actual subnets in your AVD VNet before redeploying.
param avdSubnetAddressSpace = [
'10.0.0.0/24' // pool 1 (default subnet)
'10.0.2.0/26' // large pool A (≈34 VMs)
'10.0.2.64/26' // large pool B (≈31 VMs)
'10.0.2.128/27' // pool 3
'10.0.2.160/27' // pool 4
'10.0.2.192/27' // pool 5
'10.0.2.224/27' // pool 6
]

For single-pool deployments the template default (['10.0.0.0/24']) works without override. The override is required only when adding additional subnets.

Common quick fix and its trade-off

When the symptom of "DSC extension fails on new pool's VMs, firewall logs show denies for FQDNs that are in Allow rules" first appears in a deployment, the fastest unblock is to widen avdSubnetAddressSpace to a single VNet-spanning entry (e.g., ['10.0.0.0/16'] to cover the entire VNet) and redeploy. Pros: ≈5 minutes including redeploy, no need to enumerate every subnet. Cons: any IP in the VNet now matches as a source, including future subnets that weren't intended to be session hosts. For initial unblock or audit timelines the quick fix is acceptable; for steady-state operation, replace it with the explicit per-subnet array above so an unintended subnet doesn't quietly inherit AVD egress rights.

Troubleshooting checklist

If a new pool's VMs can't reach Microsoft endpoints:

  1. Confirm the deny pattern is source-IP-based, not destination-FQDN-based. Use Query 1 of the Firewall Troubleshooting KQL below filtered to the session host's private IP. If the denies are against destinations that ARE in the Allow rule collections (e.g., *.blob.core.usgovcloudapi.net, manage.microsoft.us, fs.microsoft.com), the cause is almost certainly a missing entry in avdSubnetAddressSpace.
  2. Verify the session host's NIC subnet. Azure portal → VM → Networking → primary NIC → Subnet. Confirm that CIDR is present in the deployed avdSubnetAddressSpace.
  3. Confirm the deployed firewall policy has the expected source addresses. Azure portal → Firewall Policies → fwp-avd-prod-usgovva → any application rule collection → any rule → Source field. Should show every entry from avdSubnetAddressSpace.
  4. Redeploy the firewall policy if the source-address list is stale: az deployment group create --resource-group <shared-RG> --template-file avd-firewall.bicep --parameters <tenant>.bicepparam. Bicep diffs and updates only the rule sources; rules are live the moment the deployment completes.

Tenant-Specific Endpoints (Parameter File)

The base avd-firewall.bicep template is intentionally generic: no tenant names, no SharePoint hostnames, nothing that varies per deployment. Tenant-specific FQDNs (the SharePoint Online and OneDrive hostnames for your Microsoft 365 tenant, <tenant>.sharepoint.us, <tenant>-my.sharepoint.us, and friends) are supplied at deployment time through a Bicep parameter file.

This separation matters whenever the base template is updated. Pulling a new version of avd-firewall.bicep (a new Microsoft-required FQDN, a sovereign-cloud endpoint correction, an additional service category) does not touch the parameter file: each side evolves independently.

How the parameter is consumed

A single clientTenantFqdns array = [] parameter is declared at the top of the template. When non-empty, the template generates an application rule collection at Priority 170 named Client-Tenant-Endpoints whose targetFqdns is the parameter value. When the parameter is empty (the default), the rule collection is omitted entirely: Azure Firewall rejects rule collections that contain zero rules, so the conditional avoids deploying an empty collection.

Parameter file template

The companion file avd-firewall.example.bicepparam shipped alongside avd-firewall.bicep is the starting point for a per-tenant parameter file. Copy it, rename it (tenant.bicepparam is a fine choice), and replace the contoso placeholders with the real tenant hostnames.

Download: avd-firewall.example.bicepparam

using './avd-firewall.bicep'

param clientTenantFqdns = [
'contoso.sharepoint.us'
'contoso-my.sharepoint.us'
'contoso-files.sharepoint.us'
'contoso-myfiles.sharepoint.us'
]

The four hostnames above cover the standard SharePoint Online / OneDrive surface in GCC High. <tenant>.sharepoint.us is the root site collection host, <tenant>-my.sharepoint.us is OneDrive, and the -files / -myfiles variants are reached by the OneDrive sync client and certain Office desktop sharing flows. Adding extra entries (line-of-business apps the tenant routes through the firewall, partner endpoints, vendor APIs) is just adding strings to the array; no template changes required.

Deploy with the parameter file

Reference the parameter file with --parameters on the same az deployment group create invocation documented in Step 2 of the deployment runbook:

az deployment group create --resource-group rg-avd-prod-usgovva --template-file avd-firewall.bicep --parameters tenant.bicepparam

The CLI resolves the parameter file relative to the current directory; place it next to the template (or pass an absolute path) and the deployment picks up both the base policy and the tenant-specific collection in a single call.

Keep parameter files outside the published material

Real tenant hostnames are deployment data, not documentation. Hold the parameter files in a separate location (a private repository, a key vault secret, an internal SharePoint, or a private folder of this repo that the public build excludes) and pull the appropriate one at deployment time. The base template stays the single source of truth that every deployment can re-pull; the parameter files stay tenant-private.


Customer Application Rule Template

Customer-specific applications are added at Priority 200–299. Each customer deployment adds its own collection with a unique priority number within that range. Use this pattern when an application needs multiple rules grouped together (a primary host, a separate auth chain, a CDN, an API).

Assessment Checklist

Before deploying, inventory the applications your AVD users will access and categorize each:

  • Government portals: agency-specific web applications (common: SAM.gov, USASpending.gov, MAX.gov)
  • File sharing / transfer: SFTP servers, managed file transfer services, large file upload portals
  • Line-of-business SaaS: CRM, ERP, project management, HR systems
  • Authentication chains: OAuth providers for those SaaS apps (may require additional auth FQDNs)
  • Vendor-specific tooling: specialized software with cloud licensing or telemetry (e.g., engineering software license servers, GIS platforms)
  • Video conferencing (non-Teams): Zoom, Webex, Google Meet each have their own FQDN/port requirements
  • Print/scan services: cloud print services if local printing is required from AVD sessions

Template Structure

Collection: Customer-[AppName]
Priority: 200 (increment by 1 for each additional collection)
Action: Allow

Rules:
[AppName]-Primary HTTPS:443 [primary FQDNs] Primary application
[AppName]-Auth HTTPS:443 [auth FQDNs] OAuth/SAML auth chain
[AppName]-CDN HTTPS:443 [CDN FQDNs] Static assets / CDN
[AppName]-API HTTPS:443 [API FQDNs] API endpoints

Common Categories and Known FQDNs

CategoryCommon FQDNs to AddNotes
Salesforce*.salesforce.com, *.force.com, *.my.salesforce.comThe *.my.salesforce.com entry is required: the base *.salesforce.com does not cover custom subdomain auth redirects
ServiceNow*.service-now.com, *.servicenow.comTwo domains used across product versions
Zoom*.zoom.us, *.zoomgov.com, *.zoom.comUDP 8801–8802 may be needed for media; add network rule if required
Workday*.workday.com, *.myworkday.com, *.wd[n].myworkday.comwd[n] varies by tenant; identify your tenant's subdomain first
Adobe Acrobat (cloud)*.acrobat.com, *.arclabs.com, *.adobelogin.comLicense activation uses *.adobelogin.com: if missing, Acrobat starts in trial mode
Esri / ArcGIS*.arcgis.com, *.esri.com, *.arcgisonline.comGIS platform with many CDN subdomains; start with wildcard, narrow after logging
Identify unknown FQDNs before deny-all goes live

Before adding the deny-all rule, run the firewall in allow-with-logging mode for 2–4 weeks with session hosts in production use. Export the firewall logs, extract the unique FQDNs, and use them to build your customer-specific rule collections. The KQL queries in the Troubleshooting section below are designed for this workflow.


Firewall Troubleshooting KQL

These queries run against the Log Analytics workspace connected to your Azure Firewall diagnostic settings. The firewall must have structured (resource-specific) logging enabled, sending Application rule log to AZFWApplicationRule and Network rule log to AZFWNetworkRule. See AVD Deployment Runbook § Step 5 for the diagnostic-settings configuration. If your firewall is still on the legacy "(Azure Diagnostics)" categories, the logs land in AzureDiagnostics with a free-form msg_s column instead: these queries will return no rows until you migrate.

Query 1: All Denied Traffic (Triage)

Surfaces every denied connection (application and network rule denials) sorted by frequency.

union AZFWApplicationRule, AZFWNetworkRule
| where Action == "Deny"
| extend Destination = coalesce(Fqdn, DestinationIp)
| summarize DenyCount = count(), LastSeen = max(TimeGenerated)
by SourceIp, Destination, DestinationPort, Protocol, RuleCollection
| order by DenyCount desc
| take 100

Query 2: Single Host Investigation

When a user reports a specific application is broken, filter to their session host IP to see only their denied connections.

// Replace with the session host private IP of the affected user's session
let TargetIP = "10.x.x.x";
union AZFWApplicationRule, AZFWNetworkRule
| where Action == "Deny"
| where SourceIp == TargetIP
| extend Destination = coalesce(Fqdn, DestinationIp)
| project TimeGenerated, SourceIp, Destination, DestinationPort, Protocol, RuleCollection, Rule
| order by TimeGenerated desc

Query 3: FQDN Baseline (Before Deny-All Activation)

Run this during the allow-with-logging validation period to build your customer application rule list. This query shows every unique FQDN reached by session hosts, sorted by frequency, which becomes the input for building Priority 200+ customer collections.

// Set time range to cover representative business usage (1–2 weeks recommended)
AZFWApplicationRule
| where Action == "Allow"
| where isnotempty(Fqdn)
// Exclude already-documented infrastructure FQDNs to focus on unknown destinations
| where Fqdn !endswith ".microsoft.com"
and Fqdn !endswith ".microsoft.us"
and Fqdn !endswith ".windows.net"
and Fqdn !endswith ".usgovcloudapi.net"
| summarize
HitCount = count(),
UniqueHosts = dcount(SourceIp),
LastSeen = max(TimeGenerated)
by Fqdn, DestinationPort
| order by HitCount desc
Export and categorize the baseline

Export the results of Query 3 to CSV and sort by HitCount. The top entries by hit count are the applications your users depend on most heavily. Group the FQDNs by application (often recognizable by domain) and build one customer rule collection per application. Low-frequency FQDNs that appear from only one or two hosts are candidates for closer review before allowing.


Update Procedure

The Bicep template is the source of truth for the rule set. Do not edit rules through the Azure portal: portal edits drift silently from the template, get overwritten on the next deployment, and leave no CAB-reviewable diff. Every rule change flows through the template.

When to deploy an update

  • New application FQDNs discovered via the Query 3 baseline that need to be promoted into an allow rule.
  • Microsoft documentation changes to required endpoints for AVD, M365, Intune, or MDE that are not absorbed by the existing FQDN tags (the WindowsVirtualDesktop, Office365, MicrosoftIntune, WindowsUpdate, WindowsDiagnostics, and MicrosoftActiveProtectionService tags auto-update; changes outside those tags' scope surface as new denies in Query 1).
  • A new workload added to the AVD environment (new SaaS, new line-of-business app, new security tool).
  • Retirement of a rule for a decommissioned application.

Prerequisites

  • Azure CLI installed on the change operator's workstation, authenticated to Azure Government.
  • Read/write access to the target resource group via a PIM-activated role (typically Firewall Contributor or Network Contributor).
  • The Bicep template (avd-firewall.bicep) and the deployment script (load-firewall.azcli) under version control: every change reviewed and approved before deployment.
  • An approved CAB ticket for CM.L2-3.4.3 evidence.

Deployment script: load-firewall.azcli

The three deployment commands wrapped as a runnable Azure CLI script. Commands 1 and 2 run once per firewall; command 3 runs on every rule update. Replace the placeholder values (<subscription-guid>, <firewall-name>, <rg-name>, <policy-name>) with the customer-specific values before running.

Download: load-firewall.azcli

# Azure Firewall — load/update rule policy via Bicep (GCC High)
#
# Recommended deployment flow (see AVD Deployment Runbook Step 2):
# 1. Run section 2 of this script BEFORE provisioning the VNet/firewall —
# it creates the firewall policy + rule collection groups as a
# standalone object in the resource group.
# 2. When you provision the firewall via the Azure portal "Create virtual
# network" wizard, select the existing policy `fwp-avd-prod-usgovva`
# from the Firewall policy dropdown. The firewall is bound at creation
# time, so all rules are live the moment provisioning completes.
# 3. To update rules later, re-run section 2. Bicep is idempotent —
# it diffs against the live policy and updates only what changed.

# 1. Connect to Azure Government
az cloud set --name AzureUSGovernment
az login
az account set --subscription <subscription-guid>

# 2. Deploy / update the firewall policy from the Bicep template + tenant parameter file.
# Run this for both the initial deployment and every subsequent rule update.
# The parameter file supplies tenant-specific FQDNs (SharePoint, OneDrive, etc.) —
# see avd-firewall.example.bicepparam for the starting template.
az deployment group create --resource-group <rg-name> --template-file avd-firewall.bicep --parameters <tenant>.bicepparam

# 3. (Legacy / recovery only) Associate an existing firewall with the policy.
# Required only if the firewall was created BEFORE the policy existed —
# e.g., a pre-existing firewall using classic rules being migrated to Firewall Policy.
# In the runbook flow above, skip this — the VNet wizard binds the policy at creation time.
# az network firewall update --name <firewall-name> --resource-group <rg-name> --firewall-policy fwp-avd-prod-usgovva

Bicep template: avd-firewall.bicep

The full Azure Firewall policy expressed as a Bicep template: one resource per rule collection, parameterized on location, policy name, and AVD subnet CIDR. Deploy with the Deployment script above; the deployment is idempotent and a previous-template redeploy is the rollback path.

Download: avd-firewall.bicep

param location string = 'usgovvirginia'
param firewallPolicyName string = 'fwp-avd-prod-usgovva'

@description('Session-host subnet CIDR blocks. Every entry is added to sourceAddresses on every Allow rule, so traffic from any of these subnets is matched. Add one entry per session-host subnet in your VNet — typically one per host pool when following the Multi-Pool Variant of the deployment runbook. Omit the AzureFirewallSubnet (firewall egress does not match user-rule sourceAddresses) and any non-session-host subnet that should not have AVD egress rights. A single /24 default is provided for backwards compatibility with single-pool deployments; multi-pool deployments must list every session-host subnet explicitly or AVD traffic from unlisted subnets falls through to the deny-all-log collection.')
param avdSubnetAddressSpace array = ['10.0.0.0/24']

@description('Tenant-specific FQDNs (e.g., contoso.sharepoint.us, contoso-my.sharepoint.us). Supplied per deployment via a .bicepparam file; leave empty to deploy the base policy unchanged.')
param clientTenantFqdns array = []

// 1. Create the Firewall Policy
resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-09-01' = {
name: firewallPolicyName
location: location
properties: {
sku: {
tier: 'Standard'
}
}
}

// 2. Network Rule Collections (Evaluated First)
resource networkRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2023-09-01' = {
parent: firewallPolicy
name: 'DefaultNetworkRuleCollectionGroup'
properties: {
priority: 200
ruleCollections: [
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Essential-Ports'
priority: 200
action: { type: 'Allow' }
rules: [
{
ruleType: 'NetworkRule'
name: 'DNS'
ipProtocols: ['UDP', 'TCP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['*']
destinationPorts: ['53']
}
{
ruleType: 'NetworkRule'
name: 'IMDS'
ipProtocols: ['TCP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['169.254.169.254/32']
destinationPorts: ['80']
}
{
ruleType: 'NetworkRule'
name: 'Azure-HealthProbe'
ipProtocols: ['TCP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['168.63.129.16/32']
destinationPorts: ['80']
}
{
ruleType: 'NetworkRule'
name: 'NTP'
ipProtocols: ['UDP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['*']
destinationPorts: ['123']
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Teams-Media'
priority: 210
action: { type: 'Allow' }
rules: [
{
ruleType: 'NetworkRule'
name: 'Teams-STUN-TURN'
ipProtocols: ['UDP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['AzureCloud.usgovvirginia', 'AzureCloud.usgovariz']
destinationPorts: ['3478-3481']
}
{
ruleType: 'NetworkRule'
name: 'Teams-Media-Ephemeral'
ipProtocols: ['UDP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['AzureCloud']
destinationPorts: ['49152-53247']
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Azure-Services'
priority: 220
action: { type: 'Allow' }
rules: [
{
ruleType: 'NetworkRule'
name: 'AzureActiveDirectory'
ipProtocols: ['TCP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['AzureActiveDirectory']
destinationPorts: ['443']
}
{
ruleType: 'NetworkRule'
name: 'AzureMonitor'
ipProtocols: ['TCP']
sourceAddresses: avdSubnetAddressSpace
destinationAddresses: ['AzureMonitor']
destinationPorts: ['443']
}
{
ruleType: 'NetworkRule'
name: 'KMS-Activation'
ipProtocols: ['TCP']
sourceAddresses: avdSubnetAddressSpace
// Azure US Gov KMS endpoints (kms / azkms .core.usgovcloudapi.net) are
// published under service tag 'Internet', NOT 'AzureCloud', so the
// AzureCloud tag silently misses them and activation fails (0xC004F074).
// Microsoft documents the explicit IPs for forced-tunneling scenarios.
destinationAddresses: ['23.97.0.13/32', '52.126.105.2/32']
destinationPorts: ['1688']
}
]
}
]
}
}

// Conditional rule collection for client tenant-specific FQDNs.
// Wrapped in a ternary so the collection is omitted entirely when the
// parameter is empty (Azure Firewall rejects collections with zero rules).
var clientTenantRuleCollection = empty(clientTenantFqdns) ? [] : [
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Client-Tenant-Endpoints'
priority: 170
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'Tenant-Endpoints'
protocols: [{ protocolType: 'Https', port: 443 }]
targetFqdns: clientTenantFqdns
sourceAddresses: avdSubnetAddressSpace
}
]
}
]

// 3. Application Rule Collections (Evaluated Second)
resource applicationRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2023-09-01' = {
parent: firewallPolicy
name: 'DefaultApplicationRuleCollectionGroup'
dependsOn: [
networkRuleCollectionGroup
]
properties: {
priority: 300
ruleCollections: concat([
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'AVD-Control-Plane'
priority: 100
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'AVD-Platform'
protocols: [{ protocolType: 'Https', port: 443 }]
fqdnTags: ['WindowsVirtualDesktop']
targetFqdns: [
'*.wvd.azure.us'
'ecs.office.com'
'*.attest.azure.us'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'AVD-Deployment'
protocols: [{ protocolType: 'Https', port: 443 }]
targetFqdns: [
'*.blob.core.usgovcloudapi.net'
'*.table.core.usgovcloudapi.net'
'*.servicebus.usgovcloudapi.net'
'*.vault.usgovcloudapi.net'
'management.usgovcloudapi.net'
'pasff.usgovcloudapi.net'
'graph.microsoft.us'
'agenthubprod.azureedge.us'
'fs.microsoft.com'
'portal.azure.us'
'*.portal.azure.us'
'*.hosting.portal.azure.us'
'*.azureportal.usgovcloudapi.net'
'*.applicationinsights.us'
'*.loganalytics.us'
'*.msidentity.us'
'*.usgovtrafficmanager.net'
'*.windowsazure.us'
'*.s-microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'AVD-Deployment-Http'
protocols: [{ protocolType: 'Http', port: 80 }]
targetFqdns: [
'ctldl.windowsupdate.com'
'fs.microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Cert-Services'
priority: 110
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'Cert-Services'
protocols: [
{ protocolType: 'Https', port: 443 }
{ protocolType: 'Http', port: 80 }
]
targetFqdns: ['*.entrust.net', '*.digicert.com', '*.globalsign.com']
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'M365'
priority: 120
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'Office365'
protocols: [{ protocolType: 'Https', port: 443 }]
fqdnTags: ['Office365']
targetFqdns: [
'*.edge.skype.com'
'www.office.com'
'www.microsoft365.com'
'*.office365.us'
'*.gov.online.office365.us'
'*.usgovcloud.microsoft'
'*.usgovcloud-static.microsoft'
'*.usgovcloud-usercontent.microsoft'
'*.auth.microsoft.us'
'*.gov.us.microsoftonline.com'
'login.microsoftonline.us'
'graph.microsoftazure.us'
'entra.microsoft.us'
'*.entra.microsoft.us'
'entra.microsoft.com'
'*.entra.microsoft.com'
#disable-next-line no-hardcoded-env-urls
'login.microsoftonline.com'
'login-us.microsoftonline.com'
'loginex.microsoftonline.com'
'login.windows.net'
#disable-next-line no-hardcoded-env-urls
'graph.windows.net'
'clientconfig.microsoftonline-p.net'
'*.microsoftonline-p.com'
'*.msauth.net'
'*.msauthimages.us'
'*.msftauth.net'
'*.msftauthimages.us'
'*.cdn.office.net'
'officehome.msocdn.us'
'lpcres.delve.office.com'
'has.spserv.microsoft.com'
'officeclient.microsoft.com'
'config.svc.cloud.microsoft'
'*.officeapps.live.com'
'*.office.delivery.microsoft.com'
'officecdn.microsoft.com'
'officecdn.microsoft.com.edgesuite.net'
'office15client.microsoft.com'
'officepreviewredir.microsoft.com'
'officeredir.microsoft.com'
'r.office.microsoft.com'
'insertmedia.bing.office.net'
'to-do.microsoft.com'
'wcpstatic.microsoft.com'
'account.activedirectory.windowsazure.us'
'gov.teams.microsoft.us'
'*.gov.teams.microsoft.us'
'statics.teams.microsoft.com'
'*.nel.measure.office.net'
'attachments.office365-net.us'
'oneclient.sfx.ms'
'g.live.com'
'admin.onedrive.us'
'*.svc.ms'
'*.aadrm.us'
'*.informationprotection.azure.us'
#disable-next-line no-hardcoded-env-urls
'admin.microsoft.com'
#disable-next-line no-hardcoded-env-urls
'outlook.office365.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Intune'
protocols: [{ protocolType: 'Https', port: 443 }]
fqdnTags: ['MicrosoftIntune']
targetFqdns: [
'*.manage.microsoft.us'
// Apex domain — Azure Firewall wildcards do not match the apex,
// so 'manage.microsoft.us' must be listed explicitly alongside
// the '*.manage.microsoft.us' wildcard.
'manage.microsoft.us'
'intune.microsoft.us'
'*.dm.microsoft.us'
// Same apex/wildcard rule — 'dm.microsoft.us' apex is hit by
// device management traffic and is not covered by the wildcard.
'dm.microsoft.us'
#disable-next-line no-hardcoded-env-urls
'imeswdsc-afd-pri.manage.microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Entra-Registration'
protocols: [{ protocolType: 'Https', port: 443 }]
targetFqdns: [
'enterpriseregistration.windows.net'
'enterpriseregistration.microsoftonline.us'
]
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Windows-Management'
priority: 130
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'WindowsUpdate'
protocols: [
{ protocolType: 'Https', port: 443 }
{ protocolType: 'Http', port: 80 }
]
fqdnTags: ['WindowsUpdate']
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'WindowsDiagnostics'
protocols: [{ protocolType: 'Https', port: 443 }]
fqdnTags: ['WindowsDiagnostics']
targetFqdns: [
'*.events.data.microsoft.com'
// Connected User Experiences & Telemetry config channel (dmclient /
// svchost). Not covered by the *.events.data wildcard above.
'settings-win.data.microsoft.com'
'*.wosc.services.microsoft.com'
'*.pipe.aria.microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'WNS'
protocols: [{ protocolType: 'Https', port: 443 }]
targetFqdns: ['*.wns.windows.com']
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Store-Licensing-Activation'
protocols: [
{ protocolType: 'Https', port: 443 }
{ protocolType: 'Http', port: 80 }
]
targetFqdns: [
'*.sls.microsoft.com'
'licensing.mp.microsoft.com'
'displaycatalog.mp.microsoft.com'
'titles.gcch.mos.svc.usgovcloud.microsoft'
'services.autopatch.microsoft.us'
'storeedgefd.dsx.mp.microsoft.com'
'adl.windows.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'PowerShell-Gallery'
protocols: [{ protocolType: 'Https', port: 443 }]
// Discovery and download are DIFFERENT hosts. The API resolves the
// package version from www.powershellgallery.com, then redirects to
// cdn.powershellgallery.com for the .nupkg. Allowing only the former
// yields "Source Location '...' is not valid" and a failed download,
// which reads as a broken repository rather than a firewall block.
// Microsoft retired the psg-prod-*.azureedge.net endpoints; they are
// documented as "no longer supported" and were removed here.
// https://learn.microsoft.com/powershell/gallery/getting-started#network-access-to-the-powershell-gallery
targetFqdns: [
'www.powershellgallery.com'
'*.powershellgallery.com'
'cdn.powershellgallery.com'
'cdn.oneget.org'
'go.microsoft.com'
'aka.ms'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Azure-CLI-Install'
protocols: [{ protocolType: 'Https', port: 443 }]
// Where Microsoft publishes the Azure CLI MSI and ZIP packages.
//
// Scoped to every session-host subnet. Authorization for Azure
// administration is an Entra RBAC and PIM concern, not a firewall
// concern: ARM, the Azure portal, Graph and the PowerShell Gallery
// are reachable from every session host regardless, so restricting
// where the CLI can be downloaded would not constitute a boundary.
// The firewall is not an identity boundary.
//
// Commercial endpoint by design: Microsoft distributes the CLI from
// a single global storage account with no sovereign equivalent.
// Intentional cross-cloud entry, recorded here as CAB evidence.
#disable-next-line no-hardcoded-env-urls
targetFqdns: ['azcliprod.blob.core.windows.net']
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Bicep-CLI'
protocols: [{ protocolType: 'Https', port: 443 }]
// Where 'az bicep install' and 'az deployment ... --template-file
// <file>.bicep' fetch the Bicep CLI. Field-observed on Azure CLI
// 2.89.0: the client calls downloads.bicep.azure.com/releases/latest.
//
// NOT DOCUMENTED. Microsoft's air-gapped install guidance still
// directs you to GitHub releases, and this host appears nowhere on
// Microsoft Learn. Allowing it means a Bicep deployment works
// natively from a session host, with no GitHub rule and no
// hand-staged bicep.exe.
//
// Blocked, the failure is a TLS error rather than an HTTP one:
// "SSLEOFError ... UNEXPECTED_EOF_WHILE_READING", which is the
// firewall dropping the connection at SNI, not a broken download.
#disable-next-line no-hardcoded-env-urls
targetFqdns: ['downloads.bicep.azure.com']
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Edge-Browser'
protocols: [
{ protocolType: 'Https', port: 443 }
{ protocolType: 'Http', port: 80 }
]
targetFqdns: [
'edge.microsoft.com'
'msedge.api.cdp.microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'NCSI'
protocols: [{ protocolType: 'Http', port: 80 }]
targetFqdns: [
'www.msftconnecttest.com'
// Legacy NCSI probe — paired with msftconnecttest so the network
// status indicator resolves on hosts that still use the old probe.
'www.msftncsi.com'
'windows.msn.com'
'windows.msn.cn'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'SmartScreen-Watson'
protocols: [{ protocolType: 'Https', port: 443 }]
// SmartScreen splits browsing protection from APPLICATION REPUTATION
// across separate namespaces. checkappexec.microsoft.com is the
// app-reputation endpoint; without it, running a downloaded .exe
// shows "SmartScreen can't be reached right now" with a Run button,
// so the control fails OPEN rather than blocking.
//
// APEX ONLY. Microsoft documents this as '*.checkappexec.microsoft.com',
// but the call is to the bare domain and an Azure Firewall wildcard does
// not match an apex, so a list transcribed from that reference fails.
// https://learn.microsoft.com/defender-endpoint/standard-device-connectivity-urls-commercial#microsoft-defender-urls
targetFqdns: [
'*.smartscreen.microsoft.com'
'*.smartscreen-prod.microsoft.com'
'checkappexec.microsoft.com'
'*.urs.microsoft.com'
'*.watson.microsoft.com'
'unitedstates1.ss.wd.microsoft.us'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'CRL-OCSP'
protocols: [
{ protocolType: 'Http', port: 80 }
{ protocolType: 'Https', port: 443 }
]
targetFqdns: [
'ocsp.msocsp.com'
'mscrl.microsoft.com'
'oneocsp.microsoft.com'
'crl.microsoft.com'
'crl2.microsoft.com'
#disable-next-line no-hardcoded-env-urls
'*.pki.core.windows.net'
'www.microsoft.com'
'go.microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Defender-For-Endpoint'
priority: 140
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'MAPS'
protocols: [{ protocolType: 'Https', port: 443 }]
fqdnTags: ['MicrosoftActiveProtectionService']
// The MicrosoftActiveProtectionService FQDN tag does not carry these
// commercial MAPS endpoints in the USGov firewall, yet the Defender AV
// engine hits them for cloud-delivered protection even on GCC High.
// Apex listed alongside the wildcard (wildcards don't match the apex).
targetFqdns: [
'wdcp.microsoft.com'
'*.wdcp.microsoft.com'
'wdcpalt.microsoft.com'
'*.wdcpalt.microsoft.com'
'*.wd.microsoft.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Security-Compliance-Portals'
protocols: [{ protocolType: 'Https', port: 443 }]
// securitycenter.microsoft.us is a DIFFERENT namespace from
// security.microsoft.us and carries the GCC High MDE API
// (api-gov.securitycenter.microsoft.us). us4-v20.events.data is the
// EDR cyber data channel, documented Required for GCC High. Both from
// https://learn.microsoft.com/defender-endpoint/standard-device-connectivity-urls-gov
// Sample-submission and onboarding-package blobs are already covered
// by *.blob.core.usgovcloudapi.net in the AVD-Deployment rule.
targetFqdns: [
'*.security.microsoft.us'
'security.microsoft.us'
'compliance.microsoft.us'
'purview.microsoft.us'
'winatp-gw-usgt.microsoft.com'
'unitedstates1.cp.wd.microsoft.us'
'unitedstates1.x.cp.wd.microsoft.us'
'*.securitycenter.microsoft.us'
'securitycenter.microsoft.us'
'us4-v20.events.data.microsoft.com'
// FIELD-OBSERVED, NOT IN MICROSOFT'S PUBLISHED LISTS. A session host
// was denied mgmt-mdgw-ff.securitycenter.windows.us (note: .windows.us,
// not the documented .microsoft.us). Wildcard used because the
// instance prefix appears to be ring-specific. Re-check on each
// release; remove if Microsoft never documents it and denies stop.
'*.securitycenter.windows.us'
'securitycenter.windows.us'
]
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Third-Party-Security'
priority: 150
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'Proofpoint'
protocols: [
{ protocolType: 'Https', port: 443 }
{ protocolType: 'Http', port: 80 }
]
targetFqdns: [
'urldefense.us'
'*.urldefense.us'
'addin-us.securityeducation.com'
]
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Azure-Backup'
priority: 160
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'AzureBackup'
protocols: [{ protocolType: 'Https', port: 443 }]
fqdnTags: ['AzureBackup']
targetFqdns: [
'*.backup.windowsazure.us'
'*.queue.core.usgovcloudapi.net'
]
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Operations-Documentation'
priority: 165
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'Deployment-Runbook'
protocols: [{ protocolType: 'Https', port: 443 }]
// docs.mindline.com hosts the deployment runbook and operational
// procedures for this environment; reachable from inside the
// enclave so admins and users can follow procedures without
// leaving the session.
//
// Site search is served by Algolia DocSearch, an external service.
// Previously excluded on the reasoning that browsing was enough; that
// was reversed after field observation showed operators inside the
// enclave could open the runbook but not search it, which is the
// slower half of following a procedure.
//
// BOTH wildcards are required. Field-observed denies for a single
// search: <appid>-dsn.algolia.net plus <appid>-1, -2 and -3
// .algolianet.com. The Algolia client resolves the primary host then
// retries across the numbered failover hosts on a DIFFERENT apex, so
// allowing only *.algolia.net leaves search broken under retry.
targetFqdns: [
'docs.mindline.com'
'*.algolia.net'
'*.algolianet.com'
]
sourceAddresses: avdSubnetAddressSpace
}
{
ruleType: 'ApplicationRule'
name: 'Microsoft-Learn'
protocols: [{ protocolType: 'Https', port: 443 }]
// learn.microsoft.com is the primary citation target of the
// runbook and appendices; operators following procedures inside
// the enclave click through to it constantly. Apex only: articles
// and images render fully from the apex. Embedded videos
// (learn-video.azurefd.net) are deliberately not allowed; they are
// not needed to read documentation. Note aka.ms IS now allowed, in
// the Windows-Management PowerShell-Gallery rule, where Microsoft
// lists it as a required redirection service; it is no longer
// blocked as it was when this collection was first written.
// docs.microsoft.com is the retired hostname that redirects here.
// It needs its own entry: application rules match on the TLS SNI
// before any HTTP request is sent, so the redirect is never
// reached and older links die inside the enclave.
targetFqdns: ['learn.microsoft.com', 'docs.microsoft.com']
sourceAddresses: avdSubnetAddressSpace
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'Deny-All-Log'
priority: 4096
action: { type: 'Deny' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'Deny-All-Application'
protocols: [
{ protocolType: 'Https', port: 443 }
{ protocolType: 'Http', port: 80 }
]
targetFqdns: ['*']
sourceAddresses: avdSubnetAddressSpace
}
]
}
], clientTenantRuleCollection)
}
}

Post-deployment validation

Run these checks immediately after every deployment before closing the CAB ticket:

  1. Rule count and structure. In the Azure portal, confirm the firewall policy shows the expected collection names and priorities. The count of rules per collection should match the template. Any discrepancy means the deployment silently failed or the template does not reflect what was intended.
  2. Re-run Query 1 (All Denied Traffic). Check the 15 minutes immediately following the deployment for new denies on traffic that was previously allowed. A spike is an early warning that a rule was accidentally narrowed or removed.
  3. Smoke-test the common paths: one user signs into AVD, opens Teams, opens Outlook, opens a SharePoint site, triggers a Windows Update check. If any path that worked before the deployment now fails, compare the Bicep diff against the deployment target and prepare rollback.
  4. Export the rule listing (az network firewall policy rule-collection-group show) and attach to the CAB ticket as evidence of the post-deployment state.

Rollback

Rollback is a redeploy of the previous template:

git checkout <previous-commit> -- avd-firewall.bicep
az deployment group create --resource-group <rg-name> --template-file avd-firewall.bicep --parameters <tenant>.bicepparam
git checkout HEAD -- avd-firewall.bicep

The parameter file is not rolled back: only the template. Tenant-specific FQDNs are deployment data, not part of what's being reverted; the same parameter file deploys against the prior template state.

If a rule is actively breaking production, rollback is always faster than attempting a forward-fix.

CAB evidence

Every deployment should close its CAB ticket with:

  • The Git commit hash of the Bicep template deployed.
  • The diff between the previous and new template.
  • The az deployment group create command output.
  • The Query 1 validation result (empty result or explained exceptions).
  • The smoke-test log.

This package satisfies CM.L2-3.4.3 (Configuration Change Control) and CM.L2-3.4.4 (Security Impact Analysis) for the AVD network boundary.

📩 Don't Miss the Next Solution

Join the list to see the real-time solutions I'm delivering to my GCC High clients.