Unable to retrieve keyvault secret with user assigned managed identity - azure

This is a cross post from git.
I have a console app using "Microsoft.Azure.Services.AppAuthentication" Version="1.2.0-preview" and "Microsoft.Azure.KeyVault" Version="3.0.2".
I have a user assigned managed identity on my Windows 2019 VM.
The managed identity has been given the contributor role assignment on my keyvault and read to the resource group it lives in.
I am using a user assigned managed identity as the intention is to run a similar app in a kubernetes pod (with aad-pod identity). I have a connection string environment variable set as AzureServicesAuthConnectionString RunAs=App;<clientId of my user assigned MI>;TenantId=<tenantId>
When I try to connect to the keyvault to retrieve a secret I get a Forbidden exception:
Unhandled Exception: System.AggregateException: One or more errors
occurred. (Operation returned an invalid status code 'Forbidden') --->
Microsoft.Azure.KeyVault.Models.KeyVaultErrorException: Operation
returned an invalid status code 'Forbidden' at
Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretWithHttpMessagesAsync(String
vaultBaseUrl, String secretName, String secretVersion, Dictionary`2
customHeaders, CancellationToken cancellationToken) at
Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretAsync(IKeyVaultClient
operations, String secretIdentifier, CancellationToken
cancellationToken) at msiauth.AzureStuff.Run() in
C:\Users\aiadmin\src\azure\msiauth\tests.cs:line 50
--- End of inner exception stack trace --- at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout,
CancellationToken cancellationToken) at
System.Threading.Tasks.Task.Wait() at msiauth.Program.Main(String[]
args) in C:\Users\aiadmin\src\azure\msiauth\Program.cs:line 10
When I try to create a Resource Group using "Microsoft.Azure.Management.ResourceManager" Version="2.0.0-preview" it works fine so the user assigned MI works for that.
I tried the exact same keyvault code but with a system assigned managed identity and it worked correctly so permissions are fine and the code works.
Has anybody been able to do this in .net core?

Reading or writing secrets from or to the KeyVault is an operation on the Key Vault itself and is allowed (or not) based on the Access Policies set.
The contributor role you are referring belongs to the Azure Resource Manager RBAC system and allows to manage the KeyVault (f.e. assign access policies).
Most likely the identity that does work has both an RBAC assignment and an access policy. The one that doesn't work will need an access policy (and doesn't need an RBAC assignment)
For more on access policies see: https://learn.microsoft.com/en-us/azure/key-vault/key-vault-get-started#authorize

Related

Teams Bot Authentication with managed identity is failing with error : Failed to acquire token for client credentials

I have implemented Teams bot and authenticating it using managed identity.But getting below error:
Tried to get token using Managed Service Identity. Access token could not be acquired. Received a non-retryable error. MSI ResponseCode: BadRequest, Response: {"error":"invalid_request","error_description":"Identity not found"}
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthResultAsyncImpl(String resource, String authority, Boolean forceRefresh, CancellationToken cancellationToken)
at Microsoft.Bot.Connector.Authentication.ManagedIdentityAuthenticator.AcquireTokenAsync(Boolean forceRefresh)
at Microsoft.Bot.Connector.Authentication.Retry.Run[TResult](Func`1 task, Func`3 retryExceptionHandler)
I have created bot managed identity and using that identity while creating azure bot.I have bot code deployed on AKS(kubernetes) cluster.And added owner role to the managed identity of bot in AKS.
Based on documentation, connector service will take care of generating token based on values provided in appsettings.deve.json
What is the possible issue here?

Azure ErrorResponseException: Operation returned an invalid status code 'Forbidden' (CertificateOperations)

We have an app service that needs to access a key vault on Azure. We have 2 subscriptions, and this is working fine in one of them. The other one is new and we're getting this error (C# code in app service):
Microsoft.Azure.Management.ApiManagement.Models.ErrorResponseException:
Operation returned an invalid status code 'Forbidden'
at Microsoft.Azure.Management.ApiManagement.CertificateOperations.DeleteWithHttpMessagesAsync
(String resourceGroupName,
String serviceName,
String certificateId,
String ifMatch,
Dictionary`2 customHeaders,
CancellationToken cancellationToken)
at Microsoft.Azure.Management.ApiManagement.CertificateOperationsExtensions.DeleteAsync
(ICertificateOperations operations,
String resourceGroupName,
String serviceName,
String certificateId,
String ifMatch,
CancellationToken cancellationToken)
We already compared pretty much all resources, settings, keys, permissions, access policies, managed identities, everything that we think could be causing this issue, but it is still not working. The code is the same, so it does not come from there. Must be something obvious but this error message does absolutely not tell us what the root cause is.
Anyone could point us to the setting we're missing? If this is related to the account running the app service, how/where can we know what the account is on Azure?
In our case, the issues were:
Client certificates were actually stored in APIM and not in KV.
Service needed API Management Service Contributor permission instead of Contributor to be able to perform operations on the certificates stored in APIM.
Documentation:
https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
Contributor
-> Grants full access to manage all resources
API Management Service Contributor
-> Can manage service and the APIs

Login failed for user ''. while trying to access database using User Assigned ManagedIdentity [duplicate]

I am trying to use a User Assigned Managed Identity in one of our applications. I also read about the differences between System Assigned Managed Identity and User Assigned Managed Identity.
It is very clear to me that a System Assigned Managed Identity cannot be used locally as there you're assigning an identity to an Azure Resource.
However I am not clear if a User Assigned Managed Identity can be used locally. Only thing I could find is the following:
In my scenario, I would like to read some secrets from an Azure Key Vault. I have created a User Assigned Managed Identity and configured access policies on the Key Vault to give necessary permissions to this identity. Considering I am using this identity to access Azure Key Vault (which is an Azure resource), my expectation is that it should work regardless of the location (using JetBrains Rider as my IDE) from where my code is running.
However when I try to do something like:
var managedIdentityCredential = new ManagedIdentityCredential("managed-identity-id");
SecretClient secretClient = new(new Uri("https://mykeyvault.vault.azure.net/"), managedIdentityCredential);
KeyVaultSecret secret = await secretClient.GetSecretAsync(key);
I get the Azure.Identity.CredentialUnavailableException with ManagedIdentityCredential authentication unavailable. No Managed Identity endpoint found error message when I run the code locally:
Azure.Identity.CredentialUnavailableException: ManagedIdentityCredential authentication unavailable. No Managed Identity endpoint found.
at Azure.Identity.ManagedIdentityClient.AuthenticateAsync(Boolean async, TokenRequestContext context, CancellationToken cancellationToken)
at Azure.Identity.ManagedIdentityCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
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 Azure.Security.KeyVault.ChallengeBasedAuthenticationPolicy.AuthenticateRequestAsync(HttpMessage message, Boolean async, AuthenticationChallenge challenge)
at Azure.Security.KeyVault.ChallengeBasedAuthenticationPolicy.ProcessCoreAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.HttpPipeline.SendRequestAsync(Request request, CancellationToken cancellationToken)
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync(Request request, CancellationToken cancellationToken)
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync[TResult](RequestMethod method, Func`1 resultFactory, CancellationToken cancellationToken, String[] path)
at Azure.Security.KeyVault.Certificates.CertificateClient.GetCertificateAsync(String certificateName, CancellationToken cancellationToken)
Any insights into this will be highly appreciated.
No. User managed identity is also not supported with ManagedIdentityCredential in the local environment.
You should use DefaultAzureCredential for the code to work in local environment.
See the Note tip here.
Note
The ManagedIdentityCredential works only in Azure environments of
services that support managed identity authentication. It doesn't work
in the local environment. Use DefaultAzureCredential for the code
to work in both local and Azure environments as it will fall back to a
few authentication options including managed identity.
In case you want to use a user-asigned managed identity with the
DefaultAzureCredential when deployed to Azure, specify the
clientId.

Getting token to access Azure keyvault fails with Operation Cancelled message

We're trying to access a secret from Azure keyvault.
The code tries to get an access token that will then be used to retrieve the secret from the keyvault.
private async Task<string> GetAccessToken(string authority, string resource, string scope)
{
...
return this.useGlobalMsiRunAs ?
await tokenProviderGlobal.Value.KeyVaultTokenCallback(authority, resource, scope) :
await tokenProvider.Value.KeyVaultTokenCallback(authority, resource, scope);
}
useGlobalMsiRunAs is set to false and the code calls tokenProvider.Value.KeyVaultTokenCallback(...).
The above call fails with Access token could not be acquired. The operation was canceled
---> Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. 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://vault.azure.net, Authority: https://login.windows.net//xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. The operation was canceled.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net//xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net//xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired.
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthResultAsyncImpl(String resource, String authority, CancellationToken cancellationToken)
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.<get_KeyVaultTokenCallback>b__12_0(String authority, String resource, String scope)
at abc.xyz.Common.Service.AzureKeyVaultAccess.GetAccessToken(String authority, String resource, String scope) in d:\dbs\el\manb\private\ClientCenter\MT\Source\Common\ClientCenter.Common.NetStandard\Service\AzureKeyVaultAccess.cs:line 472
at Microsoft.Azure.KeyVault.KeyVaultCredential.PostAuthenticate(HttpResponseMessage response)
at Microsoft.Azure.KeyVault.KeyVaultCredential.ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretWithHttpMessagesAsync(String vaultBaseUrl, String secretName, String secretVersion, Dictionary`2 customHeaders, CancellationToken cancellationToken)
at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretAsync(IKeyVaultClient operations, String vaultBaseUrl, String secretName, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
We are using a managed identity, so the answer in this question didn't help.
Can someone please give some leads as to what could be wrong here?
You can use either system-assigned or user-assigned managed identity for your AKS Cluster’s Agent pool
Once you assign the system-assigned or user-assigned managed identity for your AKS Cluster’s Agent pool, you can add the access policy in your key vault with read access to the secrets
Then you would be able to access Azure Key vault secrets from your AKS cluster
Your code can use a managed identity to request access tokens for services that support Azure AD authentication. Azure takes care of rolling the credentials that are used by the service instance
To access key vault using system-assigned managed identity, you can use DefaultAzureCredential() class
If you are using user-assigned managed identity, you can use ManagedIdentityCredential() class
Reference: c# - How to use user-assigned managed identity to access Key Vault for Function App Config in Azure - Stack Overflow

Cannot create Azure AKS cluster: CreateRoleAssignmentError

I attempt to create an AKS cluster in a fresh new subscription. When a cluster is created via the web interface, eventually a CreateRoleAssignmentError error is produced with the following message:
RoleAssignmentReconciler retry timed out: autorest/azure: Service
returned an error. Status=403 Code="AuthorizationFailed" Message="The
client 'foo' with object id 'foo' does not have authorization to
perform action 'Microsoft.Authorization/roleAssignments/write' over
scope
'/subscriptions/bar/resourceGroups/MC_MyResourceGroup_mycluster_region/providers/Microsoft.Authorization/roleAssignments/az
Note that cluster is created with a manually created service principal, as per the documentation. This service principal has an "Owner" role on all Resource Groups within a subscription.
Note also that the reason I had to create a service principal manually is that the cluster could not be created otherwise in the first place. When attempted to create a cluster without explicitly specifying a service principal (that is, requesting a new one to be created automatically), another error was produced:
The credentials in ServicePrincipalProfile were invalid. Please see
https://aka.ms/aks-sp-help for more details. (Details: adal: Refresh
request failed. Status Code = '400'. Response body:
{"error":"unauthorized_client","error_description":"AADSTS700016:
Application with identifier 'foo' was
not found in the directory 'bar'.
This can happen if the application has not been installed by the
administrator of the tenant or consented to by any user in the tenant.
You may have sent your authentication request to the wrong
tenant.\r\nTrace ID:
9ec6ed81-892d-4592-b7b5-61842f5c1200\r\nCorrelation ID:
bffbb112-7348-4403-a36f-3010bf34e594\r\nTimestamp: 2019-07-13
15:48:02Z","error_codes":[700016],"timestamp":"2019-07-13
15:48:02Z","trace_id":"9ec6ed81-892d-4592-b7b5-61842f5c1200","correlation_id":"bffbb112-7348-4403-a36f-3010bf34e594","error_uri":"https://login.microsoftonline.com/error?code=700016"})
I am doing these operations on a fresh new account and a subscription using an "initial" admin user, so I would suppose all permissions should be in place all right. What can explain the errors above?
as the OP asks, here's the answer. In order to create resources in Azure (doesn't matter which resources) you need permissions of type: provider/resource/write. Same goes for edits. This basic principle applies to all the resources out there. Now lets compare owner and contributor:
I have an AKS template that needs contributor role to work + this custom role:
$role = Get-AzureRmRoleDefinition "Virtual Machine Contributor"
$role.Id = $null
$role.Name = "Assign AKS permissions to the vnet"
$role.Description = "Assign AKS permissions to the vnet for the inflation process"
$role.Actions.Clear()
$role.Actions.Add("Microsoft.Authorization/roleAssignments/write")
AKS clusters created by code using this role + contributor are fully functional.
User Access Administrator is a built-in role that you are being granted when you are the tenant admit and you grant yourself access to everything under your tenant: https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin. So it will obviously work if you grant yourself this role, but you can get away with a lot less permissions.
In my case I solved it by doing again "az login" and moving to the correct subscription,and then i tried to run the command again. It worked.
Also the reason may be you don't have the rights to create a cluster on that resource group. I had this kind of problem before,for that you should contact the person who administers you subscription to give you rights.

Resources