Home > Tutorials > Networking & Connectivity
🌐 Tutorial 22: Networking and Connectivity¶
Last Updated: 2026-04-15 | Version: 2.0 Status: ✅ Final | Maintainer: Documentation Team
Third-party references — publicly sourced, good-faith comparison
This page references non-Microsoft products and services. That information is drawn from each vendor's publicly available documentation and is offered for honest, good-faith comparison only. This is a personal project written from a Microsoft Fabric and Azure perspective; it does not claim expertise in, or authority over, any third-party product, and nothing here is an official statement by, or endorsed by, those vendors. Capabilities, pricing, and features change often — always verify against the vendor's current official documentation. Where a third-party offering is the stronger choice, we say so plainly.
🎯 Overview¶
This hands-on tutorial walks you through implementing enterprise networking for Microsoft Fabric, including Private Endpoints, ExpressRoute, VPN configurations, and multi-cloud connectivity. Essential for organizations with hybrid infrastructure or strict compliance requirements.
Source: Microsoft Fabric Security Overview
Duration: 3-4 hours Level: Advanced Prerequisites: - Azure subscription with Owner or Network Contributor role - Fabric workspace admin access - Basic understanding of Azure networking - Access to Azure CLI or PowerShell
📚 Learning Objectives¶
By the end of this tutorial, you will be able to:
- Configure Private Endpoints for Fabric
- Set up ExpressRoute for hybrid connectivity
- Implement Site-to-Site VPN
- Configure network security groups
- Enable multi-cloud shortcuts (S3, GCS)
- Meet gaming compliance network requirements
🔒 Part 1: Private Endpoints¶
Step 1.1: Architecture Overview¶
┌─────────────────────────────────────┐
│ Microsoft Fabric │
│ ┌─────────────────────────────────┐│
│ │ OneLake / Lakehouses ││
│ └─────────────────────────────────┘│
│ │ │
│ Private Endpoint │
└──────────────────┼──────────────────┘
│
┌──────────────────┼──────────────────┐
│ Private Link │
│ Service │
└──────────────────┼──────────────────┘
│
┌──────────────────────────────────┼──────────────────────────────────┐
│ Customer VNet │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Subnet │ │ Subnet │ │ Subnet (PE Subnet) │ │
│ │ (VMs/AKS) │ │ (Gateway) │ │ Private Endpoint │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Step 1.2: Create Virtual Network¶
# Variables
RESOURCE_GROUP="rg-fabric-networking"
LOCATION="eastus2"
VNET_NAME="vnet-fabric-hub"
VNET_ADDRESS="10.100.0.0/16"
# Create Resource Group
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
# Create Virtual Network
az network vnet create \
--resource-group $RESOURCE_GROUP \
--name $VNET_NAME \
--address-prefix $VNET_ADDRESS \
--location $LOCATION
# Create subnets
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name "snet-private-endpoints" \
--address-prefix "10.100.1.0/24" \
--disable-private-endpoint-network-policies true
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name "snet-gateway" \
--address-prefix "10.100.2.0/27"
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name "snet-compute" \
--address-prefix "10.100.10.0/24"
Step 1.3: Create Private DNS Zone¶
# Create Private DNS Zone for OneLake
az network private-dns zone create \
--resource-group $RESOURCE_GROUP \
--name "privatelink.dfs.fabric.microsoft.com"
# Link DNS zone to VNet
az network private-dns link vnet create \
--resource-group $RESOURCE_GROUP \
--zone-name "privatelink.dfs.fabric.microsoft.com" \
--name "link-fabric-vnet" \
--virtual-network $VNET_NAME \
--registration-enabled false
Step 1.4: Create Private Endpoint (Bicep)¶
// private-endpoint.bicep
@description('Name of the Private Endpoint')
param privateEndpointName string = 'pe-fabric-onelake'
@description('VNet Resource ID')
param vnetId string
@description('Subnet name for Private Endpoint')
param subnetName string = 'snet-private-endpoints'
@description('Fabric Workspace ID')
param fabricWorkspaceId string
@description('Location')
param location string = resourceGroup().location
var privateDnsZoneName = 'privatelink.dfs.fabric.microsoft.com'
var subnetId = '${vnetId}/subnets/${subnetName}'
// Private Endpoint
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-06-01' = {
name: privateEndpointName
location: location
properties: {
subnet: {
id: subnetId
}
privateLinkServiceConnections: [
{
name: '${privateEndpointName}-connection'
properties: {
privateLinkServiceId: fabricWorkspaceId
groupIds: [
'onelake'
]
}
}
]
}
}
// Private DNS Zone Group
resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-06-01' = {
name: 'default'
parent: privateEndpoint
properties: {
privateDnsZoneConfigs: [
{
name: 'onelake-dns'
properties: {
privateDnsZoneId: resourceId('Microsoft.Network/privateDnsZones', privateDnsZoneName)
}
}
]
}
}
output privateEndpointId string = privateEndpoint.id
output privateIpAddress string = privateEndpoint.properties.customDnsConfigs[0].ipAddresses[0]
Step 1.5: Verify Private Endpoint¶
# Check Private Endpoint status
az network private-endpoint show \
--name "pe-fabric-onelake" \
--resource-group $RESOURCE_GROUP \
--query "provisioningState"
# Verify DNS resolution (from within VNet)
nslookup onelake.dfs.fabric.microsoft.com
# Expected: Should resolve to private IP (10.100.1.x)
🔌 Part 2: ExpressRoute Configuration¶
Step 2.1: ExpressRoute Architecture¶
┌─────────────────┐ ┌─────────────────┐
│ On-Premises │ │ Microsoft │
│ Data Center │ │ Cloud │
│ │ │ │
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ Router │ │─────────│ │ MSEE │ │
│ │ (CE) │ │ ER │ │ Router │ │
│ └─────┬─────┘ │ Circuit │ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌─────┴─────┐ │ │ ┌─────┴─────┐ │
│ │ Network │ │ │ │ Azure │ │
│ │ Devices │ │ │ │ VNet │ │
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
Step 2.2: Create ExpressRoute Circuit¶
# Create ExpressRoute Circuit
az network express-route create \
--resource-group $RESOURCE_GROUP \
--name "er-fabric-circuit" \
--provider "Equinix" \
--peering-location "Chicago" \
--bandwidth 1000 \
--sku-family "MeteredData" \
--sku-tier "Premium"
# Get Service Key (provide to connectivity provider)
az network express-route show \
--resource-group $RESOURCE_GROUP \
--name "er-fabric-circuit" \
--query "serviceKey"
Step 2.3: Create ExpressRoute Gateway¶
# Create public IP for gateway
az network public-ip create \
--resource-group $RESOURCE_GROUP \
--name "pip-er-gateway" \
--sku "Standard" \
--allocation-method "Static"
# Create ExpressRoute Gateway
az network vnet-gateway create \
--resource-group $RESOURCE_GROUP \
--name "ergw-fabric" \
--vnet $VNET_NAME \
--gateway-type "ExpressRoute" \
--sku "Standard" \
--public-ip-addresses "pip-er-gateway"
# Note: Gateway creation takes 30-45 minutes
Step 2.4: Connect Circuit to Gateway¶
# Create connection (after circuit is provisioned)
az network vpn-connection create \
--resource-group $RESOURCE_GROUP \
--name "conn-er-fabric" \
--vnet-gateway1 "ergw-fabric" \
--express-route-circuit2 "/subscriptions/{sub-id}/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Network/expressRouteCircuits/er-fabric-circuit" \
--connection-type "ExpressRoute"
Step 2.5: Configure Private Peering¶
# Create private peering
az network express-route peering create \
--resource-group $RESOURCE_GROUP \
--circuit-name "er-fabric-circuit" \
--peering-type "AzurePrivatePeering" \
--peer-asn 65001 \
--primary-peer-subnet "192.168.1.0/30" \
--secondary-peer-subnet "192.168.2.0/30" \
--vlan-id 100
🛡️ Part 3: VPN Gateway Configuration¶
Step 3.1: Site-to-Site VPN Architecture¶
┌─────────────────┐ ┌─────────────────┐
│ On-Premises │ IPsec/IKEv2 │ Azure │
│ │ Tunnel │ │
│ ┌───────────┐ │ ┌──────────────┐ │ ┌───────────┐ │
│ │ VPN │ │──│ │──│ │ VPN │ │
│ │ Device │ │ │ Internet │ │ │ Gateway │ │
│ └─────┬─────┘ │ └──────────────┘ │ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌─────┴─────┐ │ │ ┌─────┴─────┐ │
│ │ Local │ │ │ │ Azure │ │
│ │ Network │ │ │ │ VNet │ │
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
Step 3.2: Create VPN Gateway¶
# Create public IP
az network public-ip create \
--resource-group $RESOURCE_GROUP \
--name "pip-vpn-gateway" \
--sku "Standard" \
--allocation-method "Static"
# Create VPN Gateway (VpnGw2 for production)
az network vnet-gateway create \
--resource-group $RESOURCE_GROUP \
--name "vpngw-fabric" \
--vnet $VNET_NAME \
--gateway-type "Vpn" \
--vpn-type "RouteBased" \
--sku "VpnGw2" \
--generation "Generation2" \
--public-ip-addresses "pip-vpn-gateway"
# Note: Gateway creation takes 30-45 minutes
Step 3.3: Create Local Network Gateway¶
# Define on-premises network
az network local-gateway create \
--resource-group $RESOURCE_GROUP \
--name "lng-onprem-datacenter" \
--gateway-ip-address "203.0.113.50" \
--local-address-prefixes "10.0.0.0/16" "172.16.0.0/16"
Step 3.4: Create VPN Connection¶
# Create Site-to-Site connection
az network vpn-connection create \
--resource-group $RESOURCE_GROUP \
--name "conn-vpn-onprem" \
--vnet-gateway1 "vpngw-fabric" \
--local-gateway2 "lng-onprem-datacenter" \
--shared-key "YourSecureSharedKey123!" \
--connection-type "IPsec"
# Configure IKE policy (Phase 1)
az network vpn-connection ipsec-policy add \
--resource-group $RESOURCE_GROUP \
--connection-name "conn-vpn-onprem" \
--dh-group "DHGroup14" \
--ike-encryption "AES256" \
--ike-integrity "SHA384" \
--ipsec-encryption "AES256" \
--ipsec-integrity "SHA256" \
--pfs-group "PFS2048" \
--sa-lifetime 28800 \
--sa-max-size 102400000
Step 3.5: On-Premises VPN Device Configuration¶
Example configuration for Cisco ASA:
! Cisco ASA Configuration for Azure VPN
crypto ikev2 policy 10
encryption aes-256
integrity sha384
group 14
prf sha384
lifetime seconds 28800
crypto ikev2 enable outside
crypto ipsec ikev2 ipsec-proposal AZURE-PROPOSAL
protocol esp encryption aes-256
protocol esp integrity sha-256
crypto ipsec profile AZURE-PROFILE
set ikev2 ipsec-proposal AZURE-PROPOSAL
set security-association lifetime kilobytes 102400000
set security-association lifetime seconds 3600
tunnel-group 20.185.xxx.xxx type ipsec-l2l
tunnel-group 20.185.xxx.xxx ipsec-attributes
ikev2 remote-authentication pre-shared-key YourSecureSharedKey123!
ikev2 local-authentication pre-shared-key YourSecureSharedKey123!
interface Tunnel1
nameif azure-tunnel
ip address 169.254.1.1 255.255.255.252
tunnel source interface outside
tunnel destination 20.185.xxx.xxx
tunnel mode ipsec ipv4
tunnel protection ipsec profile AZURE-PROFILE
route azure-tunnel 10.100.0.0 255.255.0.0 169.254.1.2
🔐 Part 4: Network Security Groups¶
Step 4.1: Create NSG for Fabric Access¶
# Create NSG
az network nsg create \
--resource-group $RESOURCE_GROUP \
--name "nsg-fabric-access"
# Allow outbound to Fabric (using Service Tags)
az network nsg rule create \
--resource-group $RESOURCE_GROUP \
--nsg-name "nsg-fabric-access" \
--name "Allow-Fabric-Outbound" \
--priority 100 \
--direction Outbound \
--access Allow \
--protocol Tcp \
--destination-address-prefixes "PowerBI" \
--destination-port-ranges 443
# Allow outbound to Storage (for OneLake)
az network nsg rule create \
--resource-group $RESOURCE_GROUP \
--nsg-name "nsg-fabric-access" \
--name "Allow-Storage-Outbound" \
--priority 110 \
--direction Outbound \
--access Allow \
--protocol Tcp \
--destination-address-prefixes "Storage" \
--destination-port-ranges 443
# Allow outbound to Microsoft Entra ID
az network nsg rule create \
--resource-group $RESOURCE_GROUP \
--nsg-name "nsg-fabric-access" \
--name "Allow-AzureAD-Outbound" \
--priority 120 \
--direction Outbound \
--access Allow \
--protocol Tcp \
--destination-address-prefixes "AzureActiveDirectory" \
--destination-port-ranges 443
Step 4.2: Associate NSG with Subnet¶
az network vnet subnet update \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name "snet-compute" \
--network-security-group "nsg-fabric-access"
☁️ Part 5: Multi-Cloud Connectivity¶
Step 5.1: AWS S3 Shortcut Configuration¶
# In Fabric Notebook - Create S3 Shortcut
# Step 1: Create S3 connection (one-time setup in Fabric portal)
# Navigate: Workspace > Settings > Manage connections > New connection
# Connection type: Amazon S3
# Configure:
# - Access Key ID: <your-access-key>
# - Secret Access Key: <your-secret-key>
# - Region: us-east-1
# Step 2: Create shortcut via notebook
shortcut_config = {
"path": "Files/external/aws-casino-data",
"target": {
"s3": {
"connection_id": "<s3-connection-id>",
"location": "s3://casino-data-lake/bronze/"
}
}
}
# Note: Shortcuts are created via UI or REST API
# This is for documentation purposes
Step 5.2: Google Cloud Storage Shortcut¶
# GCS Shortcut Configuration
# Step 1: Create GCS connection
# Navigate: Workspace > Settings > Manage connections > New connection
# Connection type: Google Cloud Storage
# Configure:
# - Service Account JSON key
# Step 2: Create shortcut
shortcut_config = {
"path": "Files/external/gcs-analytics",
"target": {
"gcs": {
"connection_id": "<gcs-connection-id>",
"location": "gs://casino-analytics-bucket/exports/"
}
}
}
Step 5.3: ADLS Gen2 Cross-Subscription¶
# ADLS Gen2 shortcut (different subscription/tenant)
# Step 1: Configure cross-tenant access
# - Register app in target tenant
# - Grant Storage Blob Data Reader role
# Step 2: Create connection with service principal
# Navigate: Workspace > Settings > Manage connections > New connection
# Connection type: Azure Data Lake Storage Gen2
# Authentication: Service Principal
# Configure:
# - Tenant ID: <target-tenant-id>
# - Client ID: <app-client-id>
# - Client Secret: <app-client-secret>
# - Storage account: <storage-account-name>
# Step 3: Create shortcut
shortcut_config = {
"path": "Files/external/partner-data",
"target": {
"adls": {
"connection_id": "<adls-connection-id>",
"location": "https://partnerstorage.dfs.core.windows.net/datalake/shared/"
}
}
}
🏛️ Part 6: Compliance Network Configuration¶
Step 6.1: PCI-DSS Network Requirements¶
// pci-dss-network.bicep
// PCI-DSS compliant network configuration
param location string = 'eastus2'
param environment string = 'prod'
// Dedicated VNet for cardholder data
resource pciVnet 'Microsoft.Network/virtualNetworks@2023-06-01' = {
name: 'vnet-pci-${environment}'
location: location
properties: {
addressSpace: {
addressPrefixes: ['10.200.0.0/16']
}
subnets: [
{
name: 'snet-cde' // Cardholder Data Environment
properties: {
addressPrefix: '10.200.1.0/24'
networkSecurityGroup: {
id: cdeNsg.id
}
privateEndpointNetworkPolicies: 'Disabled'
}
}
{
name: 'snet-dmz'
properties: {
addressPrefix: '10.200.2.0/24'
networkSecurityGroup: {
id: dmzNsg.id
}
}
}
]
}
}
// CDE Network Security Group
resource cdeNsg 'Microsoft.Network/networkSecurityGroups@2023-06-01' = {
name: 'nsg-cde-${environment}'
location: location
properties: {
securityRules: [
{
name: 'DenyAllInbound'
properties: {
priority: 4096
direction: 'Inbound'
access: 'Deny'
protocol: '*'
sourceAddressPrefix: '*'
destinationAddressPrefix: '*'
sourcePortRange: '*'
destinationPortRange: '*'
}
}
{
name: 'AllowAuthorizedInbound'
properties: {
priority: 100
direction: 'Inbound'
access: 'Allow'
protocol: 'Tcp'
sourceAddressPrefix: '10.200.2.0/24' // DMZ only
destinationAddressPrefix: '10.200.1.0/24'
sourcePortRange: '*'
destinationPortRange: '443'
}
}
]
}
}
// Enable DDoS protection
resource ddosProtection 'Microsoft.Network/ddosProtectionPlans@2023-06-01' = {
name: 'ddos-${environment}'
location: location
properties: {}
}
Step 6.2: Gaming Compliance Network (NIGC)¶
# Gaming Commission Network Requirements
# Document for audit purposes
network_segmentation:
zones:
- name: "Gaming Floor"
subnet: "10.210.1.0/24"
access: "Restricted to slot systems"
- name: "Cage Operations"
subnet: "10.210.2.0/24"
access: "Financial transactions"
- name: "Surveillance"
subnet: "10.210.3.0/24"
access: "Isolated - no external access"
- name: "Analytics"
subnet: "10.210.10.0/24"
access: "Fabric Private Endpoint access"
firewall_rules:
- source: "Gaming Floor"
destination: "Analytics"
port: 443
protocol: "HTTPS"
purpose: "Slot telemetry to Fabric"
- source: "Cage Operations"
destination: "Analytics"
port: 443
protocol: "HTTPS"
purpose: "Transaction data to Fabric"
audit_requirements:
- All network traffic logged
- 90-day retention minimum
- Real-time alerting for anomalies
- Quarterly penetration testing
📊 Part 7: Monitoring and Troubleshooting¶
Step 7.1: Network Watcher Setup¶
# Enable Network Watcher
az network watcher configure \
--resource-group $RESOURCE_GROUP \
--locations $LOCATION \
--enabled true
# Enable NSG flow logs
az network watcher flow-log create \
--resource-group $RESOURCE_GROUP \
--name "flowlog-fabric-nsg" \
--nsg "nsg-fabric-access" \
--storage-account "stfabricnetlogs" \
--enabled true \
--retention 90
Step 7.2: Connection Troubleshooting¶
# Test connectivity to Fabric endpoint
az network watcher test-connectivity \
--resource-group $RESOURCE_GROUP \
--source-resource "vm-test-client" \
--dest-address "onelake.dfs.fabric.microsoft.com" \
--dest-port 443
# Check VPN connection status
az network vpn-connection show \
--resource-group $RESOURCE_GROUP \
--name "conn-vpn-onprem" \
--query "connectionStatus"
# Check ExpressRoute circuit status
az network express-route show \
--resource-group $RESOURCE_GROUP \
--name "er-fabric-circuit" \
--query "circuitProvisioningState"
✅ Summary Checklist¶
Private Endpoints¶
- Created VNet and subnets
- Created Private DNS Zone
- Deployed Private Endpoint
- Verified DNS resolution
ExpressRoute¶
- Created ExpressRoute circuit
- Created ExpressRoute Gateway
- Configured private peering
- Connected circuit to gateway
VPN Gateway¶
- Created VPN Gateway
- Created Local Network Gateway
- Configured VPN connection
- Configured on-premises device
Security¶
- Created Network Security Groups
- Applied NSG to subnets
- Enabled flow logs
- Configured monitoring
Multi-Cloud¶
- Configured S3 shortcut
- Configured GCS shortcut
- Configured cross-subscription ADLS
📖 Additional Resources¶
🧭 Navigation¶
| Previous | Up | Next |
|---|---|---|
| ⬅️ 21-GeoAnalytics & ArcGIS | 📖 Tutorials Index | 23-SHIR & Data Gateways ➡️ |
💬 Questions or issues? Open an issue in the GitHub repository.