Reputation: 185
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
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
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
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.
Upvotes: 3
Reputation: 2440
Thank you Owns supporting your answer adding the screenshot on how to add the user identity in function app settings.
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
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
Reputation: 185
Got it working, it needed below in run.ps1
Connect-AzAccount -Identity -AccountId <Managed-User Identity> -ErrorAction SilentlyContinue
Upvotes: -1