Azure  

Azure Service Bus through APIM and generating a SAS Token

On one of my recent projects, a client application was required to place a message onto an Azure Service Bus using an HTTP endpoint rather than the Service Bus SDK and with the following constraints.

  • The client is unable to generate the Service Bus SAS token.
  • Service Bus Session Id needs to be set to the customer number found in the message to ensure ordered delivery by the consumer.
  • Custom HTTP Request Headers may be used.

I decided upon a solution that uses Azure APIM to expose the Service Bus endpoint.

  1. The first step of this solution is to create an Azure Service Bus with a queue called 'apimqueue'.

Please refer below screenshot.

Azure Service Bus through APIM and generating a SAS Token

Azure Service Bus through APIM and generating a SAS Token

2. Next, click on created queue, navigate to Shared access policy, and add' apimqueuesend' with only Send claim.

Azure Service Bus through APIM and generating a SAS Token

Azure Service Bus through APIM and generating a SAS Token

3. Click on created shared access policies and copy the primary key for further use.

Azure Service Bus through APIM and generating a SAS Token

4. Next is to create an API using the 'Blank API' template, similar to what I have done below. Note the 'Web service URL' value is the base address of the Service Bus topic URL.

Azure Service Bus through APIM and generating a SAS Token

5. Enter the Name, give your service bus's web service URL, and click on create.

Azure Service Bus through APIM and generating a SAS Token

6. Add operation based on your request, like Post, and Get Methods.

Azure Service Bus through APIM and generating a SAS Token

Refer below screen after the created operation.

Azure Service Bus through APIM and generating a SAS Token

7. Next step is to add policies to added operation.

Azure Service Bus through APIM and generating a SAS Token

8. Add the below policy as shown in the above screen.

<policies>
    <inbound>
        <base />
        <cache-lookup-value key="apimqueuesend" variable-name="apimqueuesend" />
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault&lt;string>("apimqueuesend") == null)">
                <cache-store-value key="crmsbsas" value="@{
                        string resourceUri = "https://dwproject.servicebus.windows.net/apimqueue";
                        string keyName = "apimqueuesend";
                        string key = "saskey";
                        TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
                        var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 120);
                        string stringToSign = System.Uri.EscapeDataString(resourceUri) + "\n" + expiry;
                        HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
                        var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
                        var sasToken = String.Format("SharedAccessSignature sr={0}&amp;sig={1}&amp;se={2}&amp;skn={3}",
                                        System.Uri.EscapeDataString(resourceUri),
                                        System.Uri.EscapeDataString(signature), expiry, keyName);
                        return sasToken;
                    }" duration="10" />
                <cache-lookup-value key="apimqueuesend" variable-name="apimqueuesend" />
            </when>
        </choose>
        <set-backend-service base-url="https://dwproject.servicebus.windows.net" />
        <rewrite-uri template="apimqueue/messages" />
        <set-header name="Content-Type" exists-action="override">
            <value>vnd.microsoft.servicebus.yml</value>
        </set-header>
        <set-header name="Authorization" exists-action="override">
            <value>{{apimqueuesend}}</value>
        </set-header>
        <set-header name="BrokerProperties" exists-action="override">
            <value>@{
                    var json = new JObject();
                    json.Add("MessageId", context.RequestId);
                    return json.ToString(Newtonsoft.Json.Formatting.None);
                }</value>
        </set-header>
        <set-body>@{
                JObject json = context.Request.Body.As<JObject>(preserveContent: true);
                return JsonConvert.SerializeObject(json);
            }</set-body>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
        <return-response>
            <set-status code="200" reason="OK" />
        </return-response>
    </on-error>
</policies>
Markup

9. To test added policy, please navigate to test in the APIM section. Please give the required headers and JSON data and click on send.

Azure Service Bus through APIM and generating a SAS Token

Azure Service Bus through APIM and generating a SAS Token

​​​​​​​10. Finally, Navigate to our queue and check whether the message has been received.

Azure Service Bus through APIM and generating a SAS Token