O Sertão será Cloud

Everything you need to know to integrate your Azure Service Bus with your Azure Function using the…

Everything you need to know to integrate your Azure Service Bus with your Azure Function using the Factory Pattern and TypeScript

Welcome to the sixth chapter of our exciting series on integrating Azure Functions with Azure services using the powerful SOLID principles! We’ve already explored how to connect to Azure Storage, Azure Key Vault, and Azure Web PubSub. Now, get ready to dive into the fascinating world of Azure Service Bus! 📬

What is Azure Service Bus?

Azure Service Bus is a fully managed messaging platform that allows communication between different parts of a distributed system, such as cloud applications, services, and devices. It offers a robust solution for integrating systems and ensuring reliable message delivery.

Key Components of Azure Service Bus

1. Queues

Queues in Azure Service Bus allow asynchronous communication between different parts of an application. Messages are stored in a queue until the recipient is ready to process them, ensuring ordered and reliable delivery.

2. Topics and Subscriptions

Topics enable a publish-subscribe (pub/sub) model, where messages published to a topic are delivered to multiple subscriptions. Each subscription can apply filters to receive only relevant messages, allowing flexible routing.

3. Rules and Filters

Subscriptions can use rules and filters to define specific criteria for message routing. This allows advanced customization of which messages are delivered to which subscriptions.

Advantages of Azure Service Bus

1. Reliable Delivery

Azure Service Bus ensures the delivery of messages with durability and fault tolerance. It persistently stores messages until they are successfully processed by the receiver.

2. Scalability

With horizontal scalability, Azure Service Bus can handle large volumes of messages and transactions, supporting systems of any size.

3. Security

Azure Service Bus integrates with Microsoft Entra ID and offers robust authentication and access control, ensuring that only authorized users and applications can send and receive messages.

4. Flexibility

With support for different communication patterns, such as queues, topics, and subscriptions, Azure Service Bus can be adapted to a wide variety of scenarios and system architectures.

Use Cases

1. Integration of Heterogeneous Systems

Azure Service Bus facilitates communication between systems developed in different languages and platforms, providing smooth and efficient integration.

2. Asynchronous Processing

It allows the decoupling of application components, where tasks can be queued and processed asynchronously, improving system efficiency and resilience.

3. Complex Message Routing

With topics and subscriptions, Azure Service Bus can manage complex message routing scenarios, ensuring that the right information is delivered to the right recipients.

Azure Service Bus is a powerful tool for communication and integration of distributed systems, offering reliable delivery, scalability, security, and flexibility. Whether integrating heterogeneous systems, managing asynchronous processing, or handling complex message routing, Azure Service Bus is a robust and efficient choice for cloud messaging solutions.

Step 1: Environment Setup

Before you start, make sure you have the following dependencies installed:

npm install @azure/identity @azure/keyvault-secrets

Note: If you need to see Steps 2 to 3, refer to the previous article on the topic:

Como Configurar o Azure Blob Service Client Aplicando os Princípios SOLID em uma Azure Function com…

Step 4: Setting Up the Factory for Secret Clients

Now, let’s create a factory to instantiate the ServiceBusClient using our CredentialProvider.

import { ServiceBusClient } from "@azure/service-bus";

/**
* Factory for creating instances of ServiceBusClient.
*/
class ServiceBusClientFactory {
private fullyQualifiedNamespace: string;
private credentialProvider: CredentialProvider;

/**
* Creates a new instance of ServiceBusClientFactory.
* @param {string} fullyQualifiedNamespace - The fully qualified namespace of the Azure Service Bus.
* @param {CredentialProvider} credentialProvider - The credential provider to be used.
*/
constructor(fullyQualifiedNamespace: string, credentialProvider: CredentialProvider) {
this.fullyQualifiedNamespace = fullyQualifiedNamespace;
this.credentialProvider = credentialProvider;
}

/**
* Creates an instance of ServiceBusClient.
* @returns {ServiceBusClient} A configured instance of ServiceBusClient.
*/
createServiceBusClient(): ServiceBusClient {
const credential = this.credentialProvider.getCredential();
return new ServiceBusClient(this.fullyQualifiedNamespace, credential);
}
}

Step 5: Implementing in Azure Function

Now let’s see how we can integrate this structure into an Azure Function, demonstrating each authentication method.

Example 1: Azure Function with System-assigned Managed Identity

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ServiceBusClientFactory } from "./ServiceBusClientFactory";
import { SystemAssignedManagedIdentityCredentialProvider } from "./SystemAssignedManagedIdentityCredentialProvider";

/**
* Azure Function using System-Assigned Managed Identity.
* @param {Context} context - The function context.
* @param {HttpRequest} req - The HTTP request.
* @returns {Promise<void>} A promise that resolves when the function is complete.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const fullyQualifiedNamespace = process.env.AZURE_SERVICEBUS_FULLYQUALIFIEDNAMESPACE;
const credentialProvider = new SystemAssignedManagedIdentityCredentialProvider();
const serviceClientFactory = new ServiceBusClientFactory(fullyQualifiedNamespace, credentialProvider);

const serviceClient = serviceClientFactory.createServiceBusClient();
// Use the serviceClient for operations with Service Bus
context.res = {
body: "Azure Function using System-Assigned Managed Identity for Access to Service Bus"
};
};

export default httpTrigger;

Example 2: Azure Function with User-assigned Managed Identity

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ServiceBusClientFactory } from "./ServiceBusClientFactory";
import { UserAssignedManagedIdentityCredentialProvider } from "./UserAssignedManagedIdentityCredentialProvider";

/**
* Azure Function using User-Assigned Managed Identity.
* @param {Context} context - The function context.
* @param {HttpRequest} req - The HTTP request.
* @returns {Promise<void>} A promise that resolves when the function is complete.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const fullyQualifiedNamespace = process.env.AZURE_SERVICEBUS_FULLYQUALIFIEDNAMESPACE;
const clientId = process.env.AZURE_SERVICEBUS_CLIENTID;
const credentialProvider = new UserAssignedManagedIdentityCredentialProvider(clientId);
const serviceClientFactory = new ServiceBusClientFactory(fullyQualifiedNamespace, credentialProvider);

const serviceClient = serviceClientFactory.createServiceBusClient();
// Use the serviceClient for operations with Service Bus
context.res = {
body: "Azure Function using User-Assigned Managed Identity for Access to Service Bus"
};
};

export default httpTrigger;

Example 3: Azure Function with Service Principal

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ServiceBusClientFactory } from "./ServiceBusClientFactory";
import { ServicePrincipalCredentialProvider } from "./ServicePrincipalCredentialProvider";

/**
* Azure Function using Service Principal.
* @param {Context} context - The function context.
* @param {HttpRequest} req - The HTTP request.
* @returns {Promise<void>} A promise that resolves when the function is complete.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const fullyQualifiedNamespace = process.env.AZURE_SERVICEBUS_FULLYQUALIFIEDNAMESPACE;
const tenantId = process.env.AZURE_SERVICEBUS_TENANTID;
const clientId = process.env.AZURE_SERVICEBUS_CLIENTID;
const clientSecret = process.env.AZURE_SERVICEBUS_CLIENTSECRET;
const credentialProvider = new ServicePrincipalCredentialProvider(tenantId, clientId, clientSecret);
const serviceClientFactory = new ServiceBusClientFactory(fullyQualifiedNamespace, credentialProvider);

const serviceClient = serviceClientFactory.createServiceBusClient();
// Use the serviceClient for operations with Service Bus
context.res = {
body: "Azure Function using Service Principal for Access to Service Bus"
};
};

export default httpTrigger;

Conclusion

🎉 You’ve learned how to configure Azure Functions to access Azure Service Bus using various authentication techniques and applying SOLID an Clean Code principles! Our modular and scalable approach makes maintaining and enhancing the code easier.

References

Início Rápido – Criar uma conexão de serviço no aplicativo de funções por meio do portal do Azure

Stackademic 🎓

Thank you for reading until the end. Before you go:


Everything you need to know to integrate your Azure Service Bus with your Azure Function using the… was originally published in Stackademic on Medium, where people are continuing the conversation by highlighting and responding to this story.