How to use AzureDefaultCredentials with Azure Fluent?
Asked Answered
M

2

6

I am trying to create an Azure Function in C# that regenerates storage keys. I'm struggling with finding the correct .NET library where I can authenticate and regenerate the keys.

The easiest way that I have found to authenticate is by using the DefaultAzureCredentials and passing these to BlobClient. But I can't find the option to regenerate keys anywhere on BlobClient.

The only way I found to regenerate keys on a storage account is by using Microsoft.Azure.Management.Fluent but the Fluent API does not support DefaultAzureCredentials. Instead I think I need to use SdkContext.AzureCredentialsFactory which doesn't have the automated fallback on Managed Identity and VS Code that DefaultCredentials has.

  • Is there some way to regenerate keys with BlobClient so I can use DefaultAzureCredentials?
  • Or is there a way to use DefaultAzureCredentials with the Fluent API?
Morell answered 25/2, 2021 at 11:28 Comment(0)
M
11

This is another variant that I just got to work with .NET 5.0. It uses a DefaultAzureCredential and converts it to an AzureCredentials instance. As a test, it then queries the list of ACR instances in the default subscription and prints their names. This variant is useful if you are using one or more other libraries that already support the DefaultAzureCredential.

using System;
using Azure.Core;
using Azure.Identity;
using Microsoft.Azure.Management.ResourceManager.Fluent;

namespace Program
{
    class Program
    {
        static void Main(string[] args)
        {
            var defaultCredential = new DefaultAzureCredential();
            var defaultToken = defaultCredential.GetToken(new TokenRequestContext(new[] { "https://management.azure.com/.default" })).Token;
            var defaultTokenCredentials = new Microsoft.Rest.TokenCredentials(defaultToken);
            var azureCredentials = new Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials(defaultTokenCredentials, defaultTokenCredentials, null, AzureEnvironment.AzureGlobalCloud);
            var azure = Microsoft.Azure.Management.Fluent.Azure.Configure().Authenticate(azureCredentials).WithDefaultSubscription();
            var acrList = azure.ContainerRegistries.List();
            foreach (var acr in acrList)
            {
                Console.WriteLine(acr.Name);
            }
        }
    }
}

Sources and Inspiration:

UPDATE: As Simon Opelt absolutely correctly points out in their comment: For long-running processes (e.g. services), the tokens do expire and their renewal needs to be handled. My sample here is from an Azure Function App that will run for 10 minutes max.

Mcauliffe answered 7/6, 2021 at 22:20 Comment(5)
Please be aware that for longer running scenarios (services etc.) this solution will break as soon as the token expires. For small apps like in the example it works as expected.Bellboy
@SimonOpelt Thanks a lot for pointing this out. Since I see this as very important information, I updated my answer accordingly.Mcauliffe
@SimonOpelt, MichiWerner would you please point to an example that shows how to refresh the token for a long-running process? Thank you.Predicament
Hey @PriyankPanchal , depending on what you are trying to do this might be no longer required. If the goal is running in Azure using MSI then according to this comment there should be automatic caching within the credential. Instead of getting the token once you can get one on every use without any downside. You can also see this ticket. I am not sure if there is a good token caching example around for simple use-cases.Bellboy
Thank you for the comment, @SimonOpelt. That ticket has a good amount of information that was required.Predicament
A
1

First of all: Yes, the BlobClient (and the entire SDK around that) is only for data plane operations of a Storage Account. Key rotation, however, is a management plane operation. Thus you are right, you need the Management SDK.

I also was looking for this a while ago but couldn't find a way using DefaultAzureCrendtials and the Fluent SDK. I went back to using the AzureServiceTokenProvider which also works totally fine for me:

var tenantId = Environment.GetEnvironmentVariable("tenantId");
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var token = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com", tenantId);
var tokenCredentials = new TokenCredentials(token);
log.LogInformation("Got AAD token. Creating Azure client");
var azure = Microsoft.Azure.Management.Fluent.Azure
    .Configure()
    .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
    .Authenticate(new AzureCredentials(tokenCredentials, tokenCredentials, tenantId, AzureEnvironment.AzureGlobalCloud))
    .WithDefaultSubscription();

IIRC tenantId is actually optional if you are targeting the users default tenant.

Alicia answered 25/2, 2021 at 12:53 Comment(1)
Unfortunately the documentation for AzureServiceTokenProvider mentions that the class is deprecated and you should use Azure.IdentityMorell

© 2022 - 2024 — McMap. All rights reserved.