Introducing the new Azure Function Extension Libraries **Beta**

Josh Love

10/28/21 Update – We are pleased to announce that the libraries discussed below are now GA!

We are pleased to announce the release of beta versions for Storage, Event Hubs, Service Bus, and Event Grid Functions extensions, following the new Azure SDK guidelines. This post will highlight a few new features of the libraries. We encourage you to try out the libraries and provide feedback before they go GA!

New Features

Secretless configuration

Storage, Event Hubs, and Service Bus extensions now support secretless configuration via Azure Active Directory. This allows your function app to authenticate with these services without providing a connection string as part of your function config. Here is how the configuration works for each library in the Application settings section of your function app in the portal. More details on configuring application settings for Functions apps can be found here.

Similar configuration is possible when running locally by modifying the local.settings.json file. In the local experience, you may run into a warning about missing connection strings in your local.settings.json file when using secretless configuration. This will be fixed prior to the GA of the extensions.

General setup

For all of the extensions being discussed, you will need to set the AzureWebJobsStorage setting to use a general-purpose storage account as this is required by the Functions runtime.

Name Value
AzureWebJobsStorage__accountName {account name}

For local development, you can still use Azurite by setting the value of AzureWebJobsStorage to UseDevelopmentStorage=true.

Unless otherwise specified, each of the configurations is powered by the DefaultAzureCredential type. This implies that your functions app (or your local environment when running locally) would need to be able to authenticate with the corresponding Storage account, Event Hubs namespace, or Service Bus namespace using at least one of the authentication mechanisms used by the DefaultAzureCredential.

Storage

Blobs

Name Value
MyConnection__blobServiceUri https://{account name}.blob.core.windows.net

Here is a simple function that will run whenever the specified blob is modified:

[FunctionName("BlobTriggerFunction")]
public static void Run(
    [BlobTrigger("sample-container/sample-blob", Connection = "MyConnection")]
    Stream blobStream,
    ILogger logger)
{
    using var blobStreamReader = new StreamReader(blobStream);
    logger.LogInformation($"Blob sample-container/sample-blob has been updated with content: {blobStreamReader.ReadToEnd()}");
}

Queues

Name Value
MyConnection__queueServiceUri https://{account name}.queue.core.windows.net

Here is a simple function that will run whenever a message is delivered to the specified queue:

[FunctionName("QueueTriggerFunction")]
public static void Run(
    [QueueTrigger("sample-queue", Connection = "MyConnection")] 
    string message,
    ILogger logger)
    {
        logger.LogInformation($"Received message from sample-queue, content={message}");
    }

Event Hubs

Name Value
MyConnection__fullyQualifiedNamespace {namespace name}.servicebus.windows.net

Here is a simple function that will run whenever an event is delivered to the specified event hub:

[FunctionName("EventHubTriggerFunction")]
public static void Run(
    [EventHubTrigger("<event_hub_name>", Connection = "MyConnection")]
    EventData eventData,
    ILogger logger)
{
    logger.LogInformation($"C# function triggered to process a message: {eventData.EventBody}");
    logger.LogInformation($"EnqueuedTime={eventData.EnqueuedTime}");
}

Service Bus

Name Value
MyConnection__fullyQualifiedNamespace {namespace name}.servicebus.windows.net

Here is a simple function that will run whenever a message is delivered to the specified queue:

[FunctionName("ServiceBusTriggerFunction")]
public static void Run(
    [ServiceBusTrigger("<queue_name>", Connection = "MyConnection")]
    ServiceBusReceivedMessage message,
    ILogger logger)
{
    logger.LogInformation($"C# function triggered to process a message: {message.Body}");
    logger.LogInformation($"EnqueuedTime={message.EnqueuedTime}");
}

Advanced Configuration

In each of the preceding examples, the DefaultAzureCredential type would be used by the extensions to attempt to authenticate with the service. It’s also possible to configure more fine-grained authentication. We will use Blob Storage as an example, but the same settings are available for Storage Queues, Event Hubs, and Service Bus. To configure using Managed Identity, which uses the ManagedIdentityCredential type:

Name Value
MyConnection__blobServiceUri https://{account name}.blob.core.windows.net
MyConnection__credential managedIdentity
MyConnection__clientId {myClientId}

To configure using a client secret credential, which uses the ClientSecretCredential type:

Name Value
MyConnection__blobServiceUri https://{account name}.blob.core.windows.net
MyConnection__tenantId {myTenantId}
MyConnection__clientId {myClientId}
MyConnection__clientSecret {myClientSecret}

And finally, to configure using a client certificate, which uses the ClientCertificateCredential type:

Name Value
MyConnection__blobServiceUri https://{account name}.blob.core.windows.net
MyConnection__tenantId {myTenantId}
MyConnection__clientId {myClientId}
MyConnection__certificate {myCertificate}

CloudEvent Binding

When writing a C# function, it is now possible to use the new CloudEvent type which conforms to the CloudEvents V1 schema for output functions:

Output:

[FunctionName("CloudEventBindingFunction")]
public static async Task<IActionResult> RunAsync(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
    HttpRequest req,
    [EventGrid(TopicEndpointUri = "EventGridEndpoint", TopicKeySetting = "EventGridKey")]
    IAsyncCollector<CloudEvent> eventCollector)
{
    CloudEvent e = new CloudEvent("IncomingRequest", "IncomingRequest", await req.ReadAsStringAsync());
    await eventCollector.AddAsync(e);
    return new OkResult();
}

Trigger functions are not yet supported as an Event subscription can currently only be created using the EventGridSchema from Azure Functions.

Conclusion

Azure Functions is one of Azure’s core serverless offerings, that can greatly simplify your application. The latest set of packages are our effort to make integrating with Azure functions quick and painless, allowing you to quickly jumpstart your applications and get running.

For more information about each of the extensions from this article please see the following README files:

Azure SDK Blog Contributions

Thank you for reading this Azure SDK blog post! We hope that you learned something new and welcome you to share this post. We are open to Azure SDK blog contributions. Please contact us at azsdkblog@microsoft.com with your topic and we’ll get you set up as a guest blogger.