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.
Azure SDK Links
- Azure SDK Website: aka.ms/azsdk
- Azure SDK Intro (3 minute video): aka.ms/azsdk/intro
- Azure SDK Intro Deck (PowerPoint deck): aka.ms/azsdk/intro/deck
- Azure SDK Releases: aka.ms/azsdk/releases
- Azure SDK Blog: aka.ms/azsdk/blog
- Azure SDK Twitter: twitter.com/AzureSDK
- Azure SDK Design Guidelines: aka.ms/azsdk/guide
- Azure SDKs & Tools: azure.microsoft.com/downloads
- Azure SDK Central Repository: github.com/azure/azure-sdk
- Azure SDK for .NET: github.com/azure/azure-sdk-for-net
- Azure SDK for Java: github.com/azure/azure-sdk-for-java
- Azure SDK for Python: github.com/azure/azure-sdk-for-python
- Azure SDK for JavaScript/TypeScript: github.com/azure/azure-sdk-for-js
- Azure SDK for Android: github.com/Azure/azure-sdk-for-android
- Azure SDK for iOS: github.com/Azure/azure-sdk-for-ios
- Azure SDK for Go: github.com/Azure/azure-sdk-for-go
- Azure SDK for C: github.com/Azure/azure-sdk-for-c
- Azure SDK for C++: github.com/Azure/azure-sdk-for-cpp
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.
Yes. That will work.
Will AzureWebJobsDashboard__accountName work for Azure Functions as well?
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).
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?
Tom,
Support for the .NET Worker model is planned. We just created the issues to track the work as part of the current sprint and expect to have them done soon.
You can follow the relevant issues here: https://github.com/Azure/azure-functions-dotnet-worker/issues?q=is%3Aissue+is%3Aopen+label%3Aextensions
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?
They’re currently supported with the in-process model, with the Worker model support coming soon.
are these currently or planned to be fully functional with the scale controller too?
any info on this??
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
in your App Settings to indicate your intention to use Managed Identity.
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.
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.