Radfd13
Radfd13

Reputation: 185

Unable to use 'User-managed identity' with Azure Function App

I am trying to use 'User-managed identity' with my function app. The managed id has contributor access at resource-group level where function is hosted. It's a powershell function and at the moment it only has

Write-Host "Hello World"

When I run my function I get below error:

2021-10-05T13:34:15Z   [Warning]   WARNING: Unable to acquire token for tenant 'organizations' with error 'ManagedIdentityCredential authentication failed: Service request failed.
Status: 400 (Bad Request)

Headers:
Date: Tue, 05 Oct 2021 13:34:14 GMT
Content-Length: 133
'
2021-10-05T13:34:16Z   [Error]   ERROR: ManagedIdentityCredential authentication failed: Service request failed.
Status: 400 (Bad Request)

Headers:
Date: Tue, 05 Oct 2021 13:34:14 GMT
Content-Length: 133


Exception             : 
    Type           : Azure.Identity.AuthenticationFailedException
    TargetSite     : 
        Name          : FailWrapAndThrow
        DeclaringType : Azure.Identity.CredentialDiagnosticScope, Azure.Identity, Version=1.4.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8
        MemberType    : Method
        Module        : Azure.Identity.dll
    StackTrace     : 
   at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex)
   at Azure.Identity.ManagedIdentityCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.ManagedIdentityCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Microsoft.Azure.PowerShell.Authenticators.MsalAccessTokenAcquirer.GetAccessTokenAsync(String callerClassName, String parametersLog, TokenCredential tokenCredential, TokenRequestContext requestContext, CancellationToken cancellationToken, String tenantId, String userId, String homeAccountId)
   at Microsoft.Azure.Commands.Common.Authentication.Factories.AuthenticationFactory.Authenticate(IAzureAccount account, IAzureEnvironment environment, String tenant, SecureString password, String promptBehavior, Action`1 promptAction, IAzureTokenCache tokenCache, String resourceId)
   at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.AcquireAccessToken(IAzureAccount account, IAzureEnvironment environment, String tenantId, SecureString password, String promptBehavior, Action`1 promptAction, String resourceId)
   at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.ListAccountTenants(IAzureAccount account, IAzureEnvironment environment, SecureString password, String promptBehavior, Action`1 promptAction)
   at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.Login(IAzureAccount account, IAzureEnvironment environment, String tenantId, String subscriptionId, String subscriptionName, SecureString password, Boolean skipValidation, Action`1 promptAction, String name, Boolean shouldPopulateContextList, Int32 maxContextPopulation, String authScope)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass118_2.<ExecuteCmdlet>b__5()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass118_0.<ExecuteCmdlet>b__1(AzureRmProfile localProfile, RMProfileClient profileClient, String name)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass126_0.<SetContextWithOverwritePrompt>b__0(AzureRmProfile prof, RMProfileClient client)
   at Microsoft.Azure.Commands.Profile.Common.AzureContextModificationCmdlet.ModifyContext(Action`2 contextAction)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.SetContextWithOverwritePrompt(Action`3 setContextAction)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.ExecuteCmdlet()
   at Microsoft.WindowsAzure.Commands.Utilities.Common.CmdletExtensions.<>c__3`1.<ExecuteSynchronouslyOrAsJob>b__3_0(T c)
   at Microsoft.WindowsAzure.Commands.Utilities.Common.CmdletExtensions.ExecuteSynchronouslyOrAsJob[T](T cmdlet, Action`1 executor)
   at Microsoft.WindowsAzure.Commands.Utilities.Common.CmdletExtensions.ExecuteSynchronouslyOrAsJob[T](T cmdlet)
   at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord()
    Message        : ManagedIdentityCredential authentication failed: Service request failed.
                     Status: 400 (Bad Request)
                     
                     Headers:
                     Date: Tue, 05 Oct 2021 13:34:14 GMT
                     Content-Length: 133
                     
    InnerException : 
        Type       : Azure.RequestFailedException
        Status     : 400
        TargetSite : 
            Name          : MoveNext
            DeclaringType : Azure.Identity.ManagedIdentitySource+<HandleResponseAsync>d__10, Azure.Identity, Version=1.4.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8
            MemberType    : Method
            Module        : Azure.Identity.dll
        StackTrace : 
   at Azure.Identity.ManagedIdentitySource.HandleResponseAsync(Boolean async, TokenRequestContext context, Response response, CancellationToken cancellationToken)
   at Azure.Identity.ManagedIdentitySource.AuthenticateAsync(Boolean async, TokenRequestContext context, CancellationToken cancellationToken)
   at Azure.Identity.ManagedIdentityClient.AuthenticateAsync(Boolean async, TokenRequestContext context, CancellationToken cancellationToken)
   at Azure.Identity.ManagedIdentityCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        Message    : Service request failed.
                     Status: 400 (Bad Request)
                     
                     Headers:
                     Date: Tue, 05 Oct 2021 13:34:14 GMT
                     Content-Length: 133
                     
        Source     : Azure.Identity
        HResult    : -2146233088
    Source         : Azure.Identity
    HResult        : -2146233088
CategoryInfo          : CloseError: (:) [Connect-AzAccount], AuthenticationFailedException
FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
InvocationInfo        : 
    MyCommand        : Connect-AzAccount
    ScriptLineNumber : 16
    OffsetInLine     : 5
    HistoryId        : 1
    ScriptName       : C:\home\site\wwwroot\profile.ps1
    Line             : Connect-AzAccount -Identity
                       
    PositionMessage  : At C:\home\site\wwwroot\profile.ps1:16 char:5
                       +     Connect-AzAccount -Identity
                       +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    PSScriptRoot     : C:\home\site\wwwroot
    PSCommandPath    : C:\home\site\wwwroot\profile.ps1
    InvocationName   : Connect-AzAccount
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, C:\home\site\wwwroot\profile.ps1: line 16
PipelineIterationInfo : 





2021-10-05T13:34:17Z   [Error]   Errors reported while executing profile.ps1. See logs for detailed errors. Profile location: C:\home\site\wwwroot\profile.ps1.
2021-10-05T13:34:17Z   [Information]   INFORMATION: Hello World

I have followed the steps listed in the doc here and have also double checked the function app does have IDENTITY_ENDPOINT and IDENTITY_HEADER values set.

For the life of me I can't get this to work. It does however works fine with 'System-assigned managed identity'.

I have also tried combinations of Connect-AzAccount and Set-AzContext commands, I end up getting same error.

Is any one able to point out what am I missing here, it will be highly appreciated.

Upvotes: 8

Views: 22618

Answers (5)

John Leidegren
John Leidegren

Reputation: 60997

When you use a user assigned managed identity you still need to specify which identity you want to use with what credential (since you can have more than one user assigned identity attached). To identify what identity to use, you simply specify the client ID of the manage identity.

This will depend on what method you use but the AZURE_CLIENT_ID environment variable can be used to guide the Azure.Identity package to select the user assigned managed identity you want to use.

Upvotes: 5

Laurent
Laurent

Reputation: 998

On my side I was trying to connect with cosmos DB client

But the ManagedIdentityClientId parameter was missing in the client method

string userAssignedClientId = "<USER_ASSIGNED_CLIENT_ID>";
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });

new CosmosClient

Upvotes: 9

Joe Eng
Joe Eng

Reputation: 1214

For user assigned identity connections you need to add environment variables for <CONNECTION_NAME_PREFIX>__credential and <CONNECTION_NAME_PREFIX>__clientId otherwise the function host will default to trying system assigned identity.

See: https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference?tabs=azurewebjobsstorage#common-properties-for-identity-based-connections

Upvotes: 3

SaiSakethGuduru
SaiSakethGuduru

Reputation: 2440

Thank you Owns supporting your answer adding the screenshot on how to add the user identity in function app settings.

enter image description here

Also, Need to Enable the System Assigned as well by default it will in off status need to turn it on and save as shown below

enter image description here

Below is the sample code on how to use the managed identity in Azure functions

# Replace the built-in code for Azure function
# Input bindings are passed in via param block.
param($Timer)

# Get the current universal time in the default string format
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
    Write-Host "PowerShell timer is running late!"
}

# This function app is using 'Managed Service Identity' to connect to the Azure SQL Database.
# Used help from following resources in setting up 'Managed Service Identity'
# [https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi](https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi)
# [https://www.azurecorner.com/using-managed-service-identity-in-azure-functions-to-access-azure-sql-database/](https://www.azurecorner.com/using-managed-service-identity-in-azure-functions-to-access-azure-sql-database/)
# [https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=powershell](https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=powershell)
$resourceURI = "[https://database.windows.net/](https://database.windows.net/)"
$tokenAuthURI = $env:MSI_ENDPOINT + "?resource=$resourceURI&api-version=2017-09-01"
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"Secret"="$env:MSI_SECRET"} -Uri $tokenAuthURI
$accessToken = $tokenResponse.access_token
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Data Source =azuresqlservername.database.windows.net ; Initial Catalog = azuresqldatabasename"
$SqlConnection.AccessToken = $AccessToken
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "ALTER INDEX ALL ON testRebuild REBUILD;"
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)

For further information check the Managed Identity link.

Upvotes: 0

Radfd13
Radfd13

Reputation: 185

Got it working, it needed below in run.ps1

Connect-AzAccount -Identity -AccountId <Managed-User Identity> -ErrorAction SilentlyContinue

Upvotes: -1

Related Questions