Secure Azure Service Bus with Private Endpoints & DNS Best Practices
Azure Service Bus provides a reliable cloud Messaging-as-a-Service solution and is great for creating event-driven architectures on Azure whether you are using AKS or Azure Functions. By setting up a private endpoint, you can securely access Service Bus from within a virtual network. This guide will walk you through configuring a Managed Identity, setting up a Service Bus namespace, configuring topics and queues, creating a Private Endpoint, and verifying network connectivity.
Setting Up a Managed Identity
To enable secure authentication to Service Bus, set up a User Assigned Managed Identity:
resource "azurerm_user_assigned_identity" "servicebus" {
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
name = "mi-${var.application_name}-${var.environment_name}-servicebus"
}
Configuring the Service Bus Namespace
Next, create the Service Bus namespace with a Premium SKU to ensure high availability and dedicated resources:
resource "azurerm_servicebus_namespace" "main" {
name = "sbns-${var.application_name}-${var.environment_name}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
sku = "Premium"
capacity = 2
premium_messaging_partitions = 2
identity {
type = "UserAssigned"
identity_ids = [
azurerm_user_assigned_identity.servicebus.id
]
}
}
Setting Up Queues and Topics
Create a Service Bus topic to manage message routing efficiently:
resource "azurerm_servicebus_topic" "tasks" {
name = "sbt-tasks"
namespace_id = azurerm_servicebus_namespace.main.id
partitioning_enabled = true
}
Configuring the Private Endpoint
Before proceeding, ensure that the DNS zones are set up correctly. If you are connecting to an extension network that attaches to a broader Virtual WAN (VWAN) or an existing shared network, the DNS zones must be in place before you start this process.
To enable private connectivity, reference an existing Private DNS Zone:
data "azurerm_private_dns_zone" "servicebus" {
name = "privatelink.servicebus.windows.net"
resource_group_name = var.virtual_hub.resource_group
}
Then, create the private endpoint linking to the Service Bus namespace:
resource "azurerm_private_endpoint" "servicebus" {
name = "pe-${var.application_name}-${var.environment_name}-servicebus"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
subnet_id = azurerm_subnet.shared.id
private_dns_zone_group {
name = "servicebus"
private_dns_zone_ids = [data.azurerm_private_dns_zone.servicebus.id]
}
private_service_connection {
name = "pec-${var.application_name}-${var.environment_name}-servicebus"
private_connection_resource_id = azurerm_servicebus_namespace.main.id
is_manual_connection = false
subresource_names = ["namespace"]
}
}
The key things to call out are the subnet_id is connecting us to the appropriate subnet in a Virtual Network. You need to ens ure your workloads that eventually publish and subscribe to the Service Bus have network line-of-sight to this subnet.
We are linking the existing Service Bus DNS Zone. This will actually cause a DNS record to be created for our service bus that will allow us to resolve to the private IP address.
We are linking the Service Bus Namespace using its Azure Resource ID and we are specifying the namespace sub-resource. The sub-resources change depending on the type of service you are connecting to the Private Endpoint so this has to “tick and tie” with the private_connection_resource_id and the private_dns_zone_ids . Everything needs to be marching to the same drummer.
Verify Private Network Connectivity
Once deployed, verify connectivity by resolving the private IP address of the Service Bus namespace. The resolved IP should match the Private Endpoint IP address.
Publishers gonna pub
You need to create role assignments for the “Azure Service Bus Data Sender” to allow your azure services to publish. This would be attached to whatever service you are hosting code that publishes to Service Bus.
resource "azurerm_role_assignment" "servicebus_sender_function" {
scope = data.azurerm_servicebus_namespace.main.id
role_definition_name = "Azure Service Bus Data Sender"
principal_id = azurerm_linux_function_app.main.identity[0].principal_id
}
In the above example I am granting access to the System Assigned Managed Identity of a Function App.
Subscribers gonna sub
You need to create role assignments for the “Azure Service Bus Data Receiver” role definition to allow
resource "azurerm_role_assignment" "servicebus_receiver" {
scope = data.azurerm_servicebus_namespace.main.id
role_definition_name = "Azure Service Bus Data Receiver"
principal_id = azurerm_linux_function_app.main.identity[0].principal_id
}
In the above example I am granting access to the System Assigned Managed Identity of a Function App.
resource "azurerm_servicebus_subscription" "tasks" {
name = "sbts-${var.application_name}-tasks"
topic_id = data.azurerm_servicebus_topic.tasks.id
max_delivery_count = 1
}
Conclusion
By following these steps, you can successfully set up a private, secure Azure Service Bus environment with a Private Endpoint. You need to verify it by DNS resolution, and ensure you have the proper RBAC permissions for your managed identity. Access Keys are a thing of the past! This configuration ensures secure message publishing and subscription within your virtual network while maintaining strict access control.