question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to authenticate via MSI locally

See original GitHub issue

This question was originally asked in the wrong repository. @shahabhijeet asked me to create a new issue here.

I want to login with MSI when I develop locally. The documentation isn’t update because I see nothing about the method:

SdkContext.AzureCredentialsFactory.FromMSI(new MSILoginInformation(MSIResourceType.AppService), AzureEnvironment.AzureGlobalCloud)

How can I develop locally with MSI so it will use the user selected from the Visual Studio 2017 (latest version) option “Azure Service Authentication”.

You can use this in example for getting values out of a keyvault via a KeyVaultClient.

var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));

You could also generate accesstokens in this way:

var azureServiceTokenProvider = new AzureServiceTokenProvider();
string token await azureServiceTokenProvider.GetAccessTokenAsync(RESOURCE HERE, TENANTID HERE);

After that, you could use the token to call a rest api. But I don’t want that, I want to use this library with MSI.

Getting MSI to work in Azure with fluent can be done with this workaround. I’m more interested in the local development part.

    public async Task<Azure.IAuthenticated> GetAzureConnection()
    {
        if (_azure != null)
        {
            return _azure;
        }
    
        AzureCredentials credentials;
        string localDevelopment = Environment.GetEnvironmentVariable("LocalDevelopment", EnvironmentVariableTarget.Process);
    
        if (!string.IsNullOrEmpty(localDevelopment) &&
            string.Equals(localDevelopment, "true", StringComparison.InvariantCultureIgnoreCase))
        {
            Log.LogDebug($"Get the local service principal for local login");
            var localDevSp = new Principal
            {
                UserPrincipalName = "LocalLogin",
                AppId = Environment.GetEnvironmentVariable("ClientId", EnvironmentVariableTarget.Process),
                TenantId = Environment.GetEnvironmentVariable("TenantId", EnvironmentVariableTarget.Process)
            };
            string clientSecret = Environment.GetEnvironmentVariable("ClientSecret", EnvironmentVariableTarget.Process);
            Log.LogDebug($"AppId: {localDevSp.AppId}, TenantId: {localDevSp.TenantId}");
    
            credentials = SdkContext
                .AzureCredentialsFactory
                .FromServicePrincipal(localDevSp.AppId, clientSecret, localDevSp.TenantId, AzureEnvironment.AzureGlobalCloud);
        }
        else
        {
            Log.LogDebug($"Get the MSI credentials");
    
            // Because MSI isn't really nicely supported in this nuget package disable it for now and user workaround
            ////credentials = SdkContext
            ////     .AzureCredentialsFactory
            ////     .FromMSI(new MSILoginInformation(MSIResourceType.AppService), AzureEnvironment.AzureGlobalCloud);
    
            try
            {
                // START workaround until MSI in this package is really supported
                string tenantId = Environment.GetEnvironmentVariable("TenantId", EnvironmentVariableTarget.Process);
                Log.LogDebug($"TenantId: {tenantId}");
                
                AzureServiceTokenProvider astp = new AzureServiceTokenProvider();
                string graphToken = await astp.GetAccessTokenAsync("https://graph.windows.net/", tenantId);
                AzureServiceTokenProvider astp2 = new AzureServiceTokenProvider();
                string rmToken = await astp2.GetAccessTokenAsync("https://management.azure.com/", tenantId);
    
                Log.LogDebug("Logging with tokens from Token Provider");
    
                AzureCredentials customTokenProvider = new AzureCredentials(
                    new TokenCredentials(rmToken),
                    new TokenCredentials(graphToken),
                    tenantId,
                    AzureEnvironment.AzureGlobalCloud);
    
                RestClient client = RestClient
                    .Configure()
                    .WithEnvironment(AzureEnvironment.AzureGlobalCloud)
                    .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
                    //.WithRetryPolicy(new RetryPolicy(new HttpStatusCodeErrorDetectionStrategy(), new IncrementalRetryStrategy(2, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(1))))
                    .WithCredentials(customTokenProvider)
                    .Build();
    
                return Azure.Authenticate(client, tenantId);
                // END workaround until MSI in this package is really supported
            }
            catch (Exception ex)
            {
                Log.LogError(ex, ex.Message);
                if (ex.InnerException != null)
                {
                    Log.LogError(ex.InnerException, ex.InnerException.Message);
                }
                throw;
            }
        }
    
        ServiceClientTracing.AddTracingInterceptor(new MicrosoftExtensionsLoggingTracer(Log));
        ServiceClientTracing.IsEnabled = true;
    
        _azure = Azure
            .Configure()
            .WithDelegatingHandler(new HttpLoggingDelegatingHandler())
            .WithLogLevel(HttpLoggingDelegatingHandler.Level.None)
            .Authenticate(credentials);
    
        return _azure;
    }

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:8
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
larry-laucommented, Jul 9, 2021

I went down the path of using Azure.Identity.DefaultAzureCredential which has logic to work locally and on Azure app service and call the REST endpoint https://management.azure.com directly.

I just wish SDK would leverage Azure.Identity package rather than reinventing for Fluent SDK. Other SDK like Azure.Security.KeyVault.Secrets.SecretClient supports this already. It would be nice to be able to use the same authentication mechanism when working with different azure libraries/SDK for .NET

2reactions
mastrycommented, Nov 5, 2021

33 months later the new SDK is still in beta and we still can’t use Fluent MSI implementation locally during development. I realize we have a (painful) workaround, but I really would like to see this incorporated into the Fluent API.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Authenticate .NET apps to Azure services during local ...
This article describes how to authenticate your application to Azure services when using the Azure SDK for .NET during local development ...
Read more >
How to authenticate via MSI locally · Issue #4968
I want to login with MSI when I develop locally. The documentation isn't update because I see nothing about the method: SdkContext.
Read more >
Managed Identity - how to debug locally
To authenticate by using Visual Studio: Sign in to Visual Studio and use Tools > Options to open Options. Select Azure Service Authentication, ......
Read more >
Azure Managed Service Identity And Local Development
In the case of Visual Studio, you can configure the account to use under Options -> Azure Service Authentication. By default, the accounts...
Read more >
Azure Managed Identity and Local Development - YouTube
... Azure AD authentication In this video, let us look at how you can set up your local development environment to work with...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found