It’s a classic architectural anti-pattern: hitting Azure Functions, Logic Apps, or Service Bus endpoints directly from the client.
It works during dev, but it’s a ticking time bomb for
production.
Why you should NOT expose Azure services directly:
- Security
risks – Every service becomes a public entry point
- Inconsistent
auth – Different services, different security implementations
- No
central governance – Hard to enforce throttling, validation, or IP
restrictions
- Tight
coupling – Clients depend on internal service structure
- Difficult
monitoring – No single place to observe and control traffic
Why Azure API Management (APIM) is essential:
- Acts
as a secure gateway for all client traffic
- Centralizes
authentication, authorization, and policies
- Enables
rate limiting, quotas, and validation
- Supports
request/response transformation
- Provides
analytics, logging, and observability
- Decouples
clients from backend changes by providing versioning, revisions and
mocking capabilities.
APIM is not optional in mature architectures—it’s
foundational.
This Youtube video covers almost everything for you to
get started with APIM - https://youtu.be/MdIsc38YruM?si=p5kpfahjPxjntxQ9
I'm using this post to document some of the APIM
policies.
An Azure API Management (APIM) policy is a set of rules
written in XML that define how requests and responses are handled,
transformed, secured, and controlled as they pass through APIM.
Think of it like a middleware layer / gateway logic
that sits between your client and backend.
There are bunch of useful policies available to us.
In this post i would share three policies to connect to a
service Bus
Your Client --> APIM --> APIM Policies --> Azure
Service Bus
1. Using APIM’s built-in Service Bus policy
Provide your queue name and namespace.
You can use C# expressions in policies by using @()
Below Policy takes the incoming requests from client and passes it as it is to Azure Service Bus.
<send-service-bus-message queue-name="your-queue" namespace="yours">
<payload>@(context.Request.Body.As<string>())</payload>
</send-service-bus-message>
2. Using APIM’s built-in Send Request policy
This policy utilizes send-request to Post data received from
client.
You can use this to send the data to any other azure resource as well, by setting url in <set-url> element.
<policies>
<!-- Throttle, authorize, validate, cache, or transform the requests -->
<inbound>
<base />
<send-request mode="new" response-variable-name="sbResponse" timeout="20">
<set-url>https://yourservicebusnamespace.servicebus.windows.net/yourquename/messages</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@{
return context.Request.Body.As<string>();
}</set-body>
<!-- Built-in Service Bus authentication -->
<authentication-managed-identity resource="https://servicebus.azure.net/" />
</send-request>
</inbound>
<!-- Control if and how the requests are forwarded to services -->
<backend>
<base />
</backend>
<!-- Customize the responses -->
<outbound>
<base />
</outbound>
<!-- Handle exceptions and customize error responses -->
<on-error>
<base />
</on-error>
</policies>
Important:
- Assign
Azure Service Bus Data Sender role to APIM’s Managed Identity
- This
avoids SAS keys and connection strings completely
- You
can enrich, validate, or transform payloads before sending
- Works
for both queues and topics
3. Using SAS Token
If you don't have enough privilege to assign Azure Service Bus Data Sender role to APIM’s, you can use SAS Keys.
<send-request mode="new" response-variable-name="sbresponse" timeout="20">
<set-url>https://yourservicebus.servicebus.windows.net/yourqueue/messages</set-url>
<set-method>POST</set-method>
<set-header name="Authorization" exists-action="override">
<value>SharedAccessSignature sr=https%3a%2f%2fxxxx.servicebus.windows.net%2fxxxxx&sig=xxxxxxxxx;se=xxxx&skn=RootManageSharedAccessKey</value>
</set-header>
<set-body>@{
return context.Request.Body.As<string>();
}</set-body>
</send-request>You can generate SAS token token(The value in Authorization attribute) by using primary key of the Shared Access Policy
[Reflection.Assembly]::LoadWithPartialName("System.Web")| out-null
$URI="https://your.servicebus.windows.net/yourqueue"
$Access_Policy_Name="RootManageSharedAccessKey"
$Access_Policy_Key="yourkey"
#Token expires now+300
$Expires=([DateTimeOffset]::Now.AddMonths(6)).ToUnixTimeSeconds()
$SignatureString=[System.Web.HttpUtility]::UrlEncode($URI)+ "`n" + [string]$Expires
$HMAC = New-Object System.Security.Cryptography.HMACSHA256
$HMAC.key = [Text.Encoding]::ASCII.GetBytes($Access_Policy_Key)
$Signature = $HMAC.ComputeHash([Text.Encoding]::ASCII.GetBytes($SignatureString))
$Signature = [Convert]::ToBase64String($Signature)
$SASToken = "SharedAccessSignature sr=" + [System.Web.HttpUtility]::UrlEncode($URI) + "&sig=" + [System.Web.HttpUtility]::UrlEncode($Signature) + "&se=" + $Expires + "&skn=" + $Access_Policy_Name
$SASTokenBest Practice Summary:
- Never
expose backend services directly
- Always
route external traffic through APIM
- Use Managed
Identity + RBAC for Azure resource access
#Azure #APIM #ServiceBus #CloudArchitecture #Security
#DevOps
ArreyNitesh
Email - arreynitesh@gmail.com
