Chapter 5 of 6 · Implementation

Private networking, DNS, and controlled egress

Governed foundation 3 hours in a non-production POC

Chapter 5 of 6

Implement#

1. Complete the network definition#

Set the five service IDs and the approved network IDs in artifacts/environments/sandbox.bicepparam. Configure these endpoint subresources and zones:

ServiceSubresourcePrivate DNS zone
Foundryaccountprivatelink.cognitiveservices.azure.com
Foundryaccountprivatelink.openai.azure.com
Foundryaccountprivatelink.services.ai.azure.com
Storageblobprivatelink.blob.core.windows.net
Azure AI SearchsearchServiceprivatelink.search.windows.net
Cosmos DBSqlprivatelink.documents.azure.com
Key Vaultvaultprivatelink.vaultcore.azure.net

Record the customer firewall repository or policy reference in the approved network design.

2. Run preflight and review what-if#

Set the approved scope and operator IDs:

PowerShell

$approvedSubscriptionId = $env:AZURE_SUBSCRIPTION_ID
$resourceGroup = "approved-session-02-resource-group"
$networkOperatorObjectId = "network-operator-object-id"
$dnsOperatorObjectId = "dns-operator-object-id"
$dnsScopeResourceIds = @(
  "/subscriptions/$approvedSubscriptionId/resourceGroups/approved-dns-resource-group"
)
$cutoverChangeReference = "approved-change-reference"

Bash

approved_subscription_id="${AZURE_SUBSCRIPTION_ID:-}"
resource_group="approved-session-02-resource-group"
network_operator_object_id="network-operator-object-id"
dns_operator_object_id="dns-operator-object-id"
dns_scope_resource_id="/subscriptions/$approved_subscription_id/resourceGroups/approved-dns-resource-group"
cutover_change_reference="approved-change-reference"

PowerShell

.\scripts\preflight.ps1 `
  -ApprovedSubscriptionId $approvedSubscriptionId `
  -ResourceGroupName $resourceGroup `
  -NetworkOperatorObjectId $networkOperatorObjectId `
  -DnsOperatorObjectId $dnsOperatorObjectId `
  -DnsScopeResourceId $dnsScopeResourceIds

Bash

./scripts/preflight.sh \
  --approved-subscription-id "$approved_subscription_id" \
  --resource-group-name "$resource_group" \
  --network-operator-object-id "$network_operator_object_id" \
  --dns-operator-object-id "$dns_operator_object_id" \
  --dns-scope-resource-id "$dns_scope_resource_id"

Repeat the DNS scope argument for separate zone-level assignments. Preflight rejects unresolved values, wrong scopes, missing roles or providers, mismatched service IDs, Bicep errors, and a failed resource-group what-if.

The preview must leave the approved VNet, route table, and subnets unchanged. Expect seven zones and links plus five private endpoints. Stop on a delete, replacement, Foundry deployment, hub change, unexpected resource group, or public-access change.

3. Deploy private endpoints and DNS#

PowerShell

$artifacts = Resolve-Path .\artifacts

az deployment group create `
  --resource-group $resourceGroup `
  --name rvas-s03-private-network `
  --template-file "$artifacts\infra\network\main.bicep" `
  --parameters "$artifacts\environments\sandbox.bicepparam" `
  --only-show-errors

Bash

artifacts_dir="$(cd ./artifacts && pwd)"

az deployment group create \
  --resource-group "$resource_group" \
  --name rvas-s03-private-network \
  --template-file "$artifacts_dir/infra/network/main.bicep" \
  --parameters "$artifacts_dir/environments/sandbox.bicepparam" \
  --only-show-errors

Service owners approve pending private endpoint connections. Public access stays unchanged.

Link the authoritative zones to approved client or resolver VNets. For hybrid DNS, forward the public service zones through an Azure-side DNS forwarder or Azure Private Resolver.

Firewall administrators update the named customer firewall source. Include the Microsoft Entra access rule required by Agent Service and the approved feature-specific destinations. Do not add a blanket internet rule. Bing Grounding, Websearch, and SharePoint Grounding still use public endpoints in an isolated Foundry environment; use other approved tools when every tool call must stay private.

4. Check the private path and cut over#

Run the connectivity check from the approved execution host:

PowerShell

.\scripts\connectivity-check.ps1 `
  -ParameterPath .\artifacts\environments\sandbox.bicepparam

Bash

./scripts/connectivity-check.sh \
  --parameter-path ./artifacts/environments/sandbox.bicepparam

Continue only when all configured FQDNs resolve to RFC 1918 addresses and accept TCP 443.

The team verifies the private path, saves prior state, disables public access, and then rechecks or restores.

Run the cutover script from the same host:

PowerShell

.\scripts\public-access-cutover.ps1 `
  -ApprovedSubscriptionId $approvedSubscriptionId `
  -ResourceGroupName $resourceGroup `
  -CutoverChangeReference $cutoverChangeReference `
  -ConfirmPriorStateRecorded `
  -Confirm

Bash

./scripts/public-access-cutover.sh \
  --approved-subscription-id "$approved_subscription_id" \
  --resource-group-name "$resource_group" \
  --cutover-change-reference "$cutover_change_reference" \
  --confirm-prior-state-recorded \
  --confirm

The script validates the five unique resource IDs, checks connectivity, and displays the five prior public-access states. Copy those states to the approved change record before confirmation. It sets each service to Disabled, confirms that state, then merges networkControlSession=02-private-networking-dns without replacing existing tags. The marker identifies a verified update.

If an update fails, inspect the change record and identify which services changed. Start the manual restore procedure instead of rerunning the cutover blindly.

Session 02

Private networking, DNS, and controlled egress slide deck