Back to Blog
Azure
4 min read

Azure Service Bus VNET Isolation and Power Automate

AzureService BusNetworkingPower AutomateSecurity

You want to secure your Service Bus with VNET rules or private endpoints. Then your Power Automate flows stop working. Here's how to handle this common scenario.

The Problem

Power Automate runs on Microsoft's shared infrastructure. It doesn't have a static IP range you can whitelist, and it doesn't support private endpoints natively.

When you enable network rules on Service Bus:

resource "azurerm_servicebus_namespace" "this" {
  name                = "sb-production"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  sku                 = "Premium"  # Required for network rules

  network_rule_set {
    default_action = "Deny"
    trusted_services_allowed = true  # Important!

    network_rules {
      subnet_id = azurerm_subnet.apps.id
    }
  }
}

Power Automate flows get "403 Forbidden" because they're not coming from your VNET.

Solution 1: Trusted Microsoft Services

The simplest approach - allow Microsoft first-party services:

network_rule_set {
  default_action           = "Deny"
  trusted_services_allowed = true  # This allows Power Automate
}

What this allows:

  • Azure Event Grid
  • Azure Stream Analytics
  • Azure IoT Hub
  • Azure API Management
  • Power Automate / Logic Apps
  • Azure Functions (with managed identity)

What this doesn't allow:

  • Random internet traffic
  • Traffic from other tenants' Power Automate

Solution 2: Managed Connector with On-Premises Gateway

For stricter requirements, use a data gateway:

  1. Deploy on-premises data gateway in your VNET
  2. Use Service Bus connector via the gateway
  3. Gateway connects to Service Bus via private endpoint
# Private endpoint for Service Bus
resource "azurerm_private_endpoint" "servicebus" {
  name                = "pe-servicebus"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  subnet_id           = azurerm_subnet.gateway.id

  private_service_connection {
    name                           = "psc-servicebus"
    private_connection_resource_id = azurerm_servicebus_namespace.this.id
    subresource_names              = ["namespace"]
    is_manual_connection           = false
  }
}

Solution 3: Azure Functions as Middleware

Create a Function App that Power Automate calls, which then talks to Service Bus:

// Azure Function with VNET integration
[FunctionName("SendToServiceBus")]
public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
    [ServiceBus("myqueue", Connection = "ServiceBusConnection")] IAsyncCollector<string> outputQueue)
{
    string messageBody = await new StreamReader(req.Body).ReadToEndAsync();
    await outputQueue.AddAsync(messageBody);
    return new OkResult();
}
# Function App with VNET integration
resource "azurerm_linux_function_app" "middleware" {
  name                       = "func-sb-middleware"
  resource_group_name        = azurerm_resource_group.this.name
  location                   = azurerm_resource_group.this.location
  service_plan_id            = azurerm_service_plan.this.id
  storage_account_name       = azurerm_storage_account.func.name
  storage_account_access_key = azurerm_storage_account.func.primary_access_key

  virtual_network_subnet_id = azurerm_subnet.functions.id

  site_config {
    vnet_route_all_enabled = true
  }
}

SKU Requirements

Standard SKU: No network rules available. Use Shared Access Signatures for security.

Premium SKU: Full network isolation with:

  • IP firewall rules
  • VNET service endpoints
  • Private endpoints
  • Trusted services bypass
resource "azurerm_servicebus_namespace" "premium" {
  name                = "sb-production"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  sku                 = "Premium"
  capacity            = 1  # 1, 2, 4, 8, or 16 messaging units
  premium_messaging_partitions = 1
}

IP Firewall Alternative

If you need to allow specific IPs (e.g., known partner systems):

resource "azurerm_servicebus_namespace_network_rule_set" "this" {
  namespace_id = azurerm_servicebus_namespace.this.id

  default_action                = "Deny"
  trusted_services_allowed      = true
  public_network_access_enabled = true

  ip_rules = [
    "203.0.113.0/24",  # Partner network
    "198.51.100.10"    # Specific server
  ]

  network_rules {
    subnet_id = azurerm_subnet.apps.id
  }
}

Monitoring Access

Check who's accessing your Service Bus:

AzureDiagnostics
| where ResourceProvider == "MICROSOFT.SERVICEBUS"
| where Category == "OperationalLogs"
| summarize count() by CallerIpAddress, OperationName
| order by count_ desc

Look for blocked access attempts:

AzureDiagnostics
| where ResourceProvider == "MICROSOFT.SERVICEBUS"
| where ResultType == "Unauthorized" or ResultType == "Forbidden"
| project TimeGenerated, CallerIpAddress, OperationName, ResultType

Decision Matrix

RequirementSolution
Simple, good securityTrusted services bypass
Maximum isolationData gateway + private endpoint
Standard SKUSAS tokens, no network isolation
Need audit trailPremium + diagnostic logging

Need help securing your Azure messaging infrastructure? Get in touch - we help organisations implement secure integration patterns.

Need help with your Azure environment?

Get in touch for a free consultation.

Get in Touch