Theoretical Foundation: Configure Service Endpoints for Azure Platform as a Service (PaaS)
1. Initial Intuitionβ
Imagine you live in a residential neighborhood and need to go to the bank. Normally, you exit through the main street, travel on public roads, and arrive at the bank. The route is functional but exposes you to urban traffic and all associated risks.
Now imagine the bank opens an exclusive entrance for residents of your neighborhood, accessible via an internal private street that only neighborhood residents can use. The bank remains in the same physical location, but now you access it through a private and secure path. Additionally, the bank can configure its entrance to only accept residents from your neighborhood, blocking anyone else.
Service Endpoints in Azure work exactly like this. PaaS services like Azure Storage, Azure SQL Database, and Azure Key Vault have public IP addresses. By default, your VMs access these services via the public internet. With Service Endpoints, you create a private and optimized path from your subnet directly to the PaaS service, keeping traffic within Microsoft's backbone network and allowing the service to restrict access to only your subnet.
2. Contextβ
2.1 The problem that Service Endpoints solveβ
Without Service Endpoints, when a VM in a VNet accesses a PaaS service like Azure Storage:
- Traffic leaves the VM with a private IP
- Goes through the NAT gateway or public IP of the VM/subnet
- Travels through the public internet to the Storage Account's public endpoint
- The Storage Account accepts connections from any IP on the internet
This creates two problems:
- Security: The Storage Account is exposed to any access attempt from the internet
- Performance and reliability: Traffic uses the public internet with its variabilities
Service Endpoints solves both simultaneously.
2.2 Position in the Azure connectivity ecosystemβ
2.3 Services that support Service Endpointsβ
| Service | Service Tag |
|---|---|
| Azure Storage | Microsoft.Storage |
| Azure SQL Database | Microsoft.Sql |
| Azure Cosmos DB | Microsoft.AzureCosmosDB |
| Azure Key Vault | Microsoft.KeyVault |
| Azure Service Bus | Microsoft.ServiceBus |
| Azure Event Hubs | Microsoft.EventHub |
| Azure App Service | Microsoft.Web |
| Azure Container Registry | Microsoft.ContainerRegistry |
| Azure Cognitive Services | Microsoft.CognitiveServices |
3. Building the Conceptsβ
3.1 What changes technically with Service Endpointsβ
When you enable a Service Endpoint on a subnet, two simultaneous technical changes occur:
Change 1: Routing The subnet's routing system learns a specific route to the PaaS service that goes directly to the Microsoft backbone, instead of going through the internet default gateway. Routes are automatically added to the NIC's effective route table.
Change 2: Subnet identity The subnet begins to present a virtual identity to the PaaS service. When traffic reaches the Storage Account (or other PaaS), it comes identified as "originating from subnet X of VNet Y". This allows the PaaS service to configure firewall rules based on subnet, not IP.
Critical point that confuses many: The public IP address of the PaaS service doesn't change. The Storage Account still has a public IP address. What changes is the path that traffic takes and the identity with which it arrives. Traffic still goes to the Storage's public IP, but now through Microsoft's private backbone.
3.2 Two sides of configurationβ
Service Endpoints require configuration on two sides, and both are necessary for the restriction to work:
Side 1: The subnet (VNet)
You enable the Service Endpoint on the subnet, adding the service (e.g., Microsoft.Storage) to the subnet's endpoint list.
Side 2: The PaaS service (service firewall) On the PaaS service (e.g., Storage Account), you configure the firewall rule to allow access only from the specific subnet and optionally deny everything else.
If you configure only Side 1 (subnet), traffic goes through the backbone but the Storage Account still accepts connections from anywhere. The benefit is only routing.
If you configure only Side 2 (PaaS firewall), you'll block service access but the subnet still won't have the endpoint configured, so the rule will never be satisfied.
Both sides together create real access control.
3.3 Service Endpoint Policiesβ
Service Endpoint Policies are an additional layer of control that can be applied to the subnet to restrict which specific instances of a service can be accessed.
For example: you have Service Endpoint for Microsoft.Storage enabled on the subnet. Without Service Endpoint Policy, VMs on that subnet can access any Azure Storage Account, not just your organization's. With a Service Endpoint Policy, you restrict to only specific Storage Accounts from your organization.
This prevents data exfiltration: a malicious user cannot create their own Storage Account and use the subnet's connectivity to exfiltrate data to it.
4. Structural Viewβ
5. How It Works in Practiceβ
5.1 Complete configuration flowβ
5.2 What happens to traffic after enablementβ
Before Service Endpoint:
- VM (10.0.1.4) β NAT β VM's public IP β internet β Storage's public IP
After Service Endpoint:
- VM (10.0.1.4) β Microsoft backbone β Storage's public IP (arriving identified as coming from AppSubnet subnet of myVNet VNet)
The source IP that Storage sees is still an IP from the Microsoft range (not the VM's private IP). What Storage receives is the subnet identity, not the VM's private IP. This is fundamental to understanding how PaaS firewall rules work.
5.3 Behavior with VNet Peeringβ
Service Endpoints don't automatically transit through VNet peering. If you have:
- Hub VNet with Subnet A (Service Endpoint for Storage enabled)
- Spoke VNet with Subnet B (no Service Endpoint)
VMs in Subnet B don't benefit from the Service Endpoint configured in Subnet A. Each subnet needs its own Service Endpoint configured.
5.4 Service Endpoint vs PaaS firewall impact when enabling "Deny All"β
When you enable Storage Account firewall with "Deny all public networks" and add only subnets with Service Endpoint, there's important behavior:
- Azure Portal, Azure CLI, and Azure PowerShell running on your local machine stop working to manage the Storage Account (because your local IP isn't on the allowed list)
- To work around this, temporarily add your local public IP to exceptions, or use "Allow trusted Microsoft services" so Azure services like Azure Backup and Azure Site Recovery continue working
6. Implementation Methodsβ
6.1 Azure Portalβ
Enabling Service Endpoint on subnet:
VNet > Subnets > [subnet] > Service endpoints > + Add
Select the service (e.g., Microsoft.Storage) and save. The change is applied immediately.
Configuring Storage Account firewall:
Storage Account > Networking > Firewalls and virtual networks
Select "Enabled from selected virtual networks and IP addresses", click "+ Add existing virtual network", select the VNet and subnet. If the Service Endpoint isn't enabled on the subnet yet, the portal offers to enable it directly in this step.
6.2 Azure CLIβ
Enabling Service Endpoint on subnet:
az network vnet subnet update \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--service-endpoints Microsoft.Storage
For multiple services simultaneously:
az network vnet subnet update \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--service-endpoints Microsoft.Storage Microsoft.Sql Microsoft.KeyVault
Adding network rule on Storage Account:
# Get subnet resource ID
SUBNET_ID=$(az network vnet subnet show \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--query id --output tsv)
# Add network rule on Storage Account
az storage account network-rule add \
--account-name myaccount \
--resource-group myRG \
--subnet $SUBNET_ID
Configure firewall default action to Deny:
az storage account update \
--name myaccount \
--resource-group myRG \
--default-action Deny
Allow trusted Microsoft services:
az storage account update \
--name myaccount \
--resource-group myRG \
--bypass AzureServices Logging Metrics
Check active network rules:
az storage account show \
--name myaccount \
--resource-group myRG \
--query networkRuleSet
6.3 Configuring Service Endpoint Policyβ
# Create Service Endpoint Policy
az network service-endpoint policy create \
--name MySEPolicy \
--resource-group myRG \
--location eastus
# Add definition: allow only specific Storage Accounts
az network service-endpoint policy-definition create \
--policy-name MySEPolicy \
--resource-group myRG \
--name AllowMyStorageOnly \
--service Microsoft.Storage \
--service-resources \
"/subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.Storage/storageAccounts/myaccount1" \
"/subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.Storage/storageAccounts/myaccount2"
# Associate policy to subnet
az network vnet subnet update \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--service-endpoint-policy MySEPolicy
6.4 Azure PowerShellβ
# Enable Service Endpoint on subnet
$subnet = Get-AzVirtualNetworkSubnetConfig `
-Name "AppSubnet" `
-VirtualNetwork (Get-AzVirtualNetwork -Name "myVNet" -ResourceGroupName "myRG")
$serviceEndpoint = New-AzServiceEndpointPolicy -Name "Policy1" -Location "eastus" -ResourceGroupName "myRG"
Set-AzVirtualNetworkSubnetConfig `
-Name "AppSubnet" `
-VirtualNetwork (Get-AzVirtualNetwork -Name "myVNet" -ResourceGroupName "myRG") `
-AddressPrefix $subnet.AddressPrefix `
-ServiceEndpoint "Microsoft.Storage"
# Add rule on Storage Account
$subnetId = $subnet.Id
Add-AzStorageAccountNetworkRule `
-ResourceGroupName "myRG" `
-AccountName "myaccount" `
-VirtualNetworkResourceId $subnetId
# Set default action as Deny
Update-AzStorageAccountNetworkRuleSet `
-ResourceGroupName "myRG" `
-AccountName "myaccount" `
-DefaultAction Deny
6.5 Bicepβ
// Subnet with Service Endpoints
resource appSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-05-01' = {
parent: vnet
name: 'AppSubnet'
properties: {
addressPrefix: '10.0.1.0/24'
serviceEndpoints: [
{
service: 'Microsoft.Storage'
locations: ['eastus', 'eastus2']
}
{
service: 'Microsoft.KeyVault'
locations: ['*']
}
]
}
}
// Storage Account with firewall restricted to subnet
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'myaccount'
location: location
sku: { name: 'Standard_LRS' }
kind: 'StorageV2'
properties: {
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices,Metrics,Logging'
virtualNetworkRules: [
{
id: appSubnet.id
action: 'Allow'
}
]
}
}
}
7. Control and Securityβ
7.1 What Service Endpoints DON'T doβ
This is a fundamental point that distinguishes Service Endpoints from Private Endpoints:
| Aspect | Service Endpoints | Private Endpoints |
|---|---|---|
| Service IP address | Remains public | Gets private IP in VNet |
| DNS | Resolves to public IP | Resolves to private IP |
| On-premises access via VPN/ER | Not transitive | Yes, works via VPN/ExpressRoute |
| Exfiltration protection | Requires Service Endpoint Policy | Inherent (access by specific resource) |
| Cost | Free | Cost per hour and per GB processed |
| Complexity | Simple | More complex (DNS, approval) |
Service Endpoints protect service access from outside the VNet, but don't create a private IP for the service. The service is still publicly accessible from other places you haven't blocked in the firewall.
7.2 Bypass: trusted Microsoft servicesβ
When you set defaultAction: Deny on a Storage Account firewall, some internal Azure services also lose access. The bypass option allows exemptions for:
- AzureServices: Azure Backup, Azure Site Recovery, Azure Data Factory, Azure Monitor
- Metrics: Azure Monitor can collect storage metrics
- Logging: Azure Storage Analytics can write logs
Important: AzureServices is not a security breach: only Microsoft services with managed identity and native integration can access through this mechanism, not arbitrary resources.
7.3 Permissions to configure Service Endpointsβ
| Operation | Minimum Permission |
|---|---|
| Enable Service Endpoint on subnet | Network Contributor on VNet |
| Add network rule on Storage Account | Storage Account Contributor |
| Create Service Endpoint Policy | Network Contributor |
| Associate Service Endpoint Policy to subnet | Network Contributor on VNet and Policy |
8. Decision Makingβ
8.1 Service Endpoints vs Private Endpointsβ
| Situation | Best Choice | Reason |
|---|---|---|
| Azure VM access to Storage, no private IP requirement | Service Endpoint | Simpler, free |
| Requirement for on-premises access via ExpressRoute | Private Endpoint | Service Endpoint is not transitive via VPN/ER |
| Compliance requiring service to have private IP | Private Endpoint | Service Endpoint maintains public IP |
| Environment with hundreds of subnets | Service Endpoint | Scales more simply |
| Total isolation per resource (not per service) | Private Endpoint | Service Endpoint protects per service, not per instance |
| Zero additional connectivity cost | Service Endpoint | Private Endpoint has hourly cost |
| Private DNS resolution mandatory | Private Endpoint | Service Endpoint doesn't change DNS |
8.2 With or without Service Endpoint Policyβ
| Situation | Use SEP? | Reason |
|---|---|---|
| Corporate environment with multiple Storage Accounts | Yes | Prevents access to Storage Accounts from other tenants |
| Controlled development environment | Optional | Less critical if all resources are from same tenant |
| Data exfiltration prevention requirement | Yes | SEP is the main defense in this scenario |
| Only one accessible Storage Account | Yes (simplifies) | Reinforces that only that resource is accessible |
8.3 Locations in Service Endpointβ
When enabling a Service Endpoint, you can specify which regions it applies to. Use * for all regions or specify individual regions.
| Scenario | Location configuration |
|---|---|
| Storage Account in the same region as VNet | Specify the region + paired region |
| Storage Account in any region | Use * |
| Geographic data restriction | Specify only the region where data should be located |
9. Best Practicesβ
- Always configure both sides: enable the Service Endpoint on the subnet AND configure the PaaS firewall. Only one side doesn't create access restriction.
- Use
defaultAction: Denyon the PaaS firewall after configuring subnet exceptions. Without this configuration, any internet IP can still access the service. - Add Service Endpoint Policies in corporate environments to prevent data exfiltration. Without SEP, an employee can create a personal Storage Account and access it through the corporate VNet.
- Configure bypass for
AzureServicesif services like Azure Backup need to access the Storage Account. - Enable Service Endpoints only on subnets that actually need PaaS access. Don't enable on all VNet subnets for convenience.
- Remember to include paired regions when configuring the Service Endpoint for Storage, as Storage Accounts with GRS replicate to the paired region and access must work during failover.
- Combine with NSGs: the Service Endpoint ensures that Storage only accepts from the subnet; the NSG ensures that the VM can only connect to the necessary endpoint on outbound.
- Prefer Private Endpoints when the requirement includes access from on-premises environments or when private name resolution is necessary.
10. Common Errorsβ
| Error | Why it happens | How to avoid |
|---|---|---|
| Firewall configured but VMs still blocked | Service Endpoint not enabled on subnet | Check if the endpoint is in the subnet's service endpoints list |
| Service Endpoint enabled but access not restricted | PaaS firewall defaultAction is still "Allow" | Change defaultAction to "Deny" after configuring rules |
| Azure Backup fails after enabling firewall | bypass: AzureServices not configured | Add AzureServices to bypass in firewall |
| On-premises access fails even with Service Endpoint | Service Endpoints don't transit via VPN/ExpressRoute | Use Private Endpoint for on-premises access |
| VM in another VNet cannot access via Service Endpoint | Service Endpoints don't transit via VNet peering automatically | Enable Service Endpoint on spoke VNet subnet as well |
| Local CLI/PowerShell tools stop working | defaultAction: Deny blocks administrator's local IP | Add administrator's public IP to exceptions during configuration |
| Service Endpoint Policy blocks legitimate Storage Account | Storage Account not included in policy list | Check and update the allowed resources list in SEP |
| Forgot paired region in Service Endpoint | GRS replicates to different region; access fails on failover | Include paired region when configuring endpoint locations |
11. Operation and Maintenanceβ
11.1 Checking active Service Endpoints on a subnetβ
az network vnet subnet show \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--query serviceEndpoints \
--output table
11.2 Checking network rules on Storage Accountβ
az storage account show \
--name myaccount \
--resource-group myRG \
--query networkRuleSet \
--output json
The output shows defaultAction, list of virtualNetworkRules, list of ipRules and bypass configuration.
11.3 Checking effective routes on NICβ
After enabling Service Endpoint, you can verify that the service route was added automatically:
az network nic show-effective-route-table \
--name myVM-NIC \
--resource-group myRG \
--output table
Look for routes with nextHopType: VirtualNetworkServiceEndpoint pointing to the service IP prefixes. This confirms that traffic is being routed through the Microsoft backbone.
11.4 Important limitsβ
| Aspect | Limit |
|---|---|
| Service Endpoints per subnet | Multiple services allowed simultaneously |
| Service Endpoint Policies per subnet | 1 per service |
| Definitions per Service Endpoint Policy | 100 |
| Supported services | Growing list (see Azure documentation) |
| Cost | Free (no additional cost) |
| IPv6 compatibility | Not supported (IPv4 only) |
12. Integration and Automationβ
12.1 Azure Policy to ensure Service Endpoints usageβ
# Policy: Storage Accounts must have virtual network restricted
az policy assignment create \
--name "storage-network-restriction" \
--policy "2a1a9cdf-e04d-429a-8416-3bfb72a1b26f" \
--scope "/subscriptions/<sub-id>"
This built-in policy audits Storage Accounts without virtual network restriction configured.
Custom policy to deny creating Storage Accounts without Service Endpoint configured:
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Storage/storageAccounts"
},
{
"field": "Microsoft.Storage/storageAccounts/networkAcls.defaultAction",
"equals": "Allow"
}
]
},
"then": {
"effect": "deny"
}
}
12.2 Integration with Azure SQL Databaseβ
For SQL Database, the configuration is similar but uses Service Tag Microsoft.Sql:
# Enable Service Endpoint for SQL on subnet
az network vnet subnet update \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--service-endpoints Microsoft.Sql
# Add VNet rule on SQL Server
az sql server vnet-rule create \
--server mySqlServer \
--resource-group myRG \
--name AllowAppSubnet \
--vnet-name myVNet \
--subnet AppSubnet
SQL Server automatically checks if the Microsoft.Sql Service Endpoint is enabled on the subnet before accepting the rule.
12.3 Integration with Key Vaultβ
# Enable Service Endpoint for Key Vault
az network vnet subnet update \
--vnet-name myVNet \
--name AppSubnet \
--resource-group myRG \
--service-endpoints Microsoft.KeyVault
# Add network rule on Key Vault
az keyvault network-rule add \
--name myKeyVault \
--resource-group myRG \
--vnet-name myVNet \
--subnet AppSubnet
# Set default action as Deny
az keyvault update \
--name myKeyVault \
--resource-group myRG \
--default-action Deny
13. Final Summaryβ
Essential concepts:
- Service Endpoints create an optimized network path from the subnet directly to the PaaS service through the Microsoft backbone, without going through the public internet.
- The PaaS service keeps its public IP address but traffic doesn't use the internet.
- Configuration requires both sides: enable the endpoint on the subnet (VNet) AND configure the PaaS service firewall to accept only that subnet.
- Without
defaultAction: Denyon the PaaS firewall, the restriction is not effective, as the service still accepts any origin.
Critical differences:
- Service Endpoint vs Private Endpoint: Service Endpoint doesn't create private IP; Private Endpoint does. Service Endpoint doesn't transit via VPN/ExpressRoute; Private Endpoint does. Service Endpoint is free; Private Endpoint has cost.
- Only subnet, without SEP: VMs on the subnet can access any instance of that PaaS service in any Azure tenant. Service Endpoint Policy restricts to specific instances.
- Service Endpoints and VNet Peering: Not transitive. Each spoke subnet needs its own Service Endpoint if it needs to access the PaaS.
What needs to be remembered:
- Enabling only the Service Endpoint on the subnet without configuring the PaaS firewall doesn't create access restriction, only improves routing.
- Service Endpoint Policies prevent data exfiltration by restricting which specific service instances are accessible.
- The
AzureServicesbypass is necessary for services like Azure Backup to continue working whendefaultAction: Denyis active. - Service Endpoints are free and don't add cost beyond existing infrastructure.
- For access from on-premises environments (via VPN or ExpressRoute) to PaaS services, use Private Endpoints, as Service Endpoints are not accessible transitively via gateways.
- After enabling the Service Endpoint, check the NIC's effective routes to confirm that the
VirtualNetworkServiceEndpointroute was added.