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.

13 comments

Discussion is closed. Login to edit/delete existing comments.

  • Mattias Fjellström 0

    Can I try out this feature for functions written in TypeScript? I’ve removed the extension bundle that is used in regular TypeScript functions and installed the correct blob storage extension using “func extensions install …” but I am having trouble getting my functions to run. It seems like the new settings in function.json are not recognized.

    • Josh LoveMicrosoft employee 0

      Hi Mattias,
      Would you mind sharing the contents of your function.json so I can try to troubleshoot? Also, feel free to submit this as an issue to the GitHub repo.

  • Chris DaMour 0

    are these currently or planned to be fully functional with the scale controller too?

    • Chris DaMour 0

      any info on this??

      • Kar Shin LinMicrosoft employee 0

        Hi Chris,

        The Scale Controller should support identity-based connections as well for these triggers/bindings! The only limitation as of now is we do not support User Assigned identities (expect this in a week or two!). Remember to specify

        MyConnection__credential = managedidentity

        in your App Settings to indicate your intention to use Managed Identity.

  • Chris DaMour 0

    are these planned to work with the in process 3.1 function apps? or do you have to use the out of process 5 stuff?

    • Fabio CavalcanteMicrosoft employee 0

      They’re currently supported with the in-process model, with the Worker model support coming soon.

  • Tom Robinson 0

    I noticed that there are beta packages for Microsoft.Azure.WebJobs.Extensions.* but not for Microsoft.Azure.Functions.Worker.Extensions.*

    Will there be support for .NET 5 functions using the Azure Functions .NET Worker at some point?

  • Michiel van Oosterhout 0

    Will AzureWebJobsDashboard__accountName work for Azure Functions as well?

    • Paul Batum 0

      No. We recommend you use appinsights instead of the dashboard (and you remove the AzureWebJobsDashboard setting from your function apps, as it has pretty bad perf impact and the dashboard is not recieving further updates).

  • Jeff Froustet 0

    What if you’re not using the SDK or a binding, but just want to replace the AzureWebJobsStorage connection string with AzureWebJobsStorage__accountName in Function App settings? I deploy to Consumption apps from VS Code, and I’d really like to be able to disable storage account key access.

    • Paul Batum 0

      Yes. That will work.

Feedback usabilla icon