Timer triggers with host storage locks using IAzureClientFactory

36 Views Asked by At

I am running a standalone application and using the Microsoft.Azure.WebJobs SDK. I am currently using Microsoft.Azure.WebJobs.Host.Storage (v 5.0.0) and a TimeTrigger. To inject Azure SDK clients I usually use Microsoft.Extensions.Azure integration as described here which lets me inject named clients and control the TokenCredential used for each client. I want to connect to the host storage with my injected client, but it seems the package isn't actually using it, instead it uses the DefaultAzureCredential (trying VS credentials, Managed Identity credentials, etc).

Is there a way to make Microsoft.Azure.WebJobs.Host.Storage resolve the blob service provider for the host storage through the injected IAzureClientFactory?

Program.cs:

hostBuilder.ConfigureWebJobs(serviceBuilder =>
{
    serviceBuilder.Services.AddAzureClients(builder =>
    {
        builder.AddClient<BlobServiceClient, BlobClientOptions>((options, credentials, serviceProvider) =>
        {
            TokenCredential tokenCredential = new MyTokenCredential();

            return new BlobServiceClient(new Uri("https://<my-storage>.blob.core.windows.net"), credential: tokenCredential, options);
        });
    });

    serviceBuilder.AddAzureStorageCoreServices();
    serviceBuilder.AddTimers();
});

MyTokenCredential.cs:

public class MyTokenCredential : TokenCredential
{
    public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
    {
        Console.WriteLine("Test1");

        return default;
    }

    public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
    {
        Console.WriteLine("Test2");

        return default;
    }
}

Function.cs:

public async Task Invoke5MinFlowJobsAsync([TimerTrigger("00:05:00", RunOnStartup = false)] TimerInfo timerInfo)
{
    await _service.DoSomethingAsync("5 min");
}

appsettings.json:

"AzureWebJobsStorage": {
  "blobServiceUri": "https://<my-storage>.blob.core.windows.net"
},
1

There are 1 best solutions below

7
SiddheshDesai On

It appears that you're attempting to incorporate a custom token credential to access Azure Storage within your Azure Functions application using the IAzureClientFactory. However, the Microsoft.Azure.WebJobs.Host.Storage package doesn't directly facilitate this approach for authentication. Instead, it depends on the AzureWebJobsStorage setting from appsettings.json or local.settings.json to configure the storage connection.

You can add this setting -AzureWebJobsStorage:"connectionstring"* in Azure Web app Environment Variables.***

Function Timer Trigger code:-

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;

namespace FunctionApp2
{
    public class Function1
    {
        [FunctionName("Function1")]
        public async Task Run([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log)
        {
            log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

            string connectionString = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
            string containerName = "data";
            string blobName = "Test.txt";

            BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
            BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
            BlobClient blobClient = containerClient.GetBlobClient(blobName);

            BlobDownloadInfo download = await blobClient.DownloadAsync();

            using (MemoryStream ms = new MemoryStream())
            {
                await download.Content.CopyToAsync(ms);
                string blobContent = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                log.LogInformation($"Blob content: {blobContent}");
            }
        }
    }
}

enter image description here

My local.settings.json:-

{
    "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=siliconstrg54;AccountKey=xxxxxxxxx3/TWrxxxxfaw==;EndpointSuffix=core.windows.net",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}