5
votes

I managed to get the below code to work (complete code here) to use Azure managed identity to authenticate (via Visual Studio) and have access to Azure storage account without using credentials.

const string storageResource = "https://storage.azure.com/";

var authResult = await azureServiceTokenProvider.GetAuthenticationResultAsync(storageResource, cancellationToken: cancellationToken);

The code managed to find my user logged in to Visual Studio and uses it to get the token and all goes well.

However, this code is executed as part of a library integration tests in an Azure DevOps build pipeline.

I found the service principal created when I created the service connection to Azure in Azure DevOps and gave it the same Storage Blob Data Contributor role hoping that Azure DevOps would use it to run the code but had no success.

So my question is:

How do I get code that runs in Azure DevOps build pipeline to be able to authenticate using the AzureServiceTokenProvider?

BTW, the error message:

Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException : Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: . Exception Message: Tried the following 3 methods to get an access token, but none of them worked. Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: . Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. Failed after 5 retries. MSI ResponseCode: BadRequest, Response: {"error":"invalid_request","error_description":"Identity not found"} Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: . Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio Token provider file not found at "C:\Users\VssAdministrator\AppData\Local.IdentityService\AzureServiceAuth\tokenprovider.json" Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: . Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. ERROR: Please run 'az login' to setup account.

TearDown : System.NullReferenceException : Object reference not set to an instance of an object.

3
Were you able to find an answer for this? I'm having the same issue.HockeyJ
@HockeyJ, so sorry but right now I don’t remember what was the problem.Fabio Milheiro

3 Answers

3
votes

When you create a service connection in Azure DevOps you are presented with (as of writing) 4 options.

  • Service principal (aka app registrations in your Azure Active Directory)
  • Manage identity
  • Publish Profile

New Azure service connection

A publish profile is an Azure App Service specific authentication mechanism that lets you publish via Kudu.

Manage identities are somewhat mislabeled. They are used to allow a VM running your Azure pipelines to act as the managed identity of that VM (you then give this managed identity access to the resources you want it to be able to access in the Azure Portal). This is somewhat backwards from how the other authentication methods work but I guess it makes sense when you are hosting your own Azure pipelines on VMs in Azure. This option has this caveat.

The AzureServiceTokenProvider will only work from within an environment that expose the MSI_ENDPOINT (aka IDENTITY_ENDPOINT). Hosted Azure DevOps pipelines are not such environments.

Service principals is what you will be using in all likelihood.

Service principals come in two flavours automatic and manual. Again with the mislabeling. There's actually nothing automatic with the automatic option the only thing that happens is that it provisions the service principal in your Azure AD for you. It will grant the service principal the contributor role at the subscription level (which means full access to everything in the subscription except access control). You should not grant service principals that kind of access. It is excessive. Remember that you service principals are just protected by credentials, that if they leak, they allow anyone to do irreparable harm.

0
votes

Since, this question hasn't been answered so far, you can try this: Try passing the connection information expicitly to the azureServiceTokenProvider. Now, the followig codeblock assumes that you're using a shared secret credential to sign into Azure AD but can be extended to any methods described here - Service-to-service authentication to Azure Key Vault using .NET

var azureServicesAuthString = $"RunAs=App;AppId={AppId};TenantId={TenantId};AppKey={ClientSecret}";
tokenProvider = new AzureServiceTokenProvider(connectionString: azureServicesAuthString);
var authResult = await azureServiceTokenProvider.GetAuthenticationResultAsync(storageResource, cancellationToken: cancellationToken);
-1
votes

You will need to create a service connection of type "Managed identity authentication" to use managed identity in DevOps pipeline.