4
votes

I'm trying to get a secret from a key vault using an Azure function, but the key vault returns forbidden when I try to access it. Clearly I'm missing something, but I haven't been able to find another post with the same problem. Code below:

AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
KeyVaultClient kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));

//(https://keyvaultname.vault.azure.net/)
var keyVaultUrl = Environment.GetEnvironmentVariable("KeyVaultLocation"); 

//(name of the secret)
var vaultSecretKey = Environment.GetEnvironmentVariable("VaultSecretKey"); 

var value = (await kvClient.GetSecretAsync(keyVaultUrl, vaultSecretKey)).Value;

I'm outputting exceptions to the log, and the last line where I await the value of the secret throws this exception:

Operation returned an invalid status code 'Forbidden'.

I have already registered the function in the key vault's access policies and given it permissions to get secrets, and I've enabled Managed Service Identity for the function. Is there something else I'm missing? I'm at a loss as to why the function can't access the vault.

7
According to your description, if you have enable MSI and give permission in key vault's access policies, it will work fine. You could check if you have click Save after you give permission in access policies.Joey Cai
I'm facing the same issue. Enabled MSI for the function app and gave it the required access in the access policy of the KeyVault. But returns Forbidden. One point to note is I can access the KeyVault from a function app I created for testing purpose in my personal subscription, but can't from within my project's subscription.Kayes

7 Answers

3
votes

Here is how I use the KeyVaultClient in my Azure Function (v2). I have a method that returns an access token based on the app ID and secret configured for the Vault:

/// <summary>
/// Called by the KeyVaultClient instance.
/// </summary>
/// <param name="authority"></param>
/// <param name="resource"></param>
/// <param name="scope"></param>
/// <returns></returns>
private static async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
{
    var clientCredential = new ClientCredential(Constants.Vault.AppId, Constants.Vault.AppSecret);

    var context = new AuthenticationContext(authority, TokenCache.DefaultShared);

    AuthenticationResult result = await context.AcquireTokenAsync(resource, clientCredential);

    return result.AccessToken;
}

Then, when I actually need to access the vault, I call the following constructor:

...
//  Pushes the encryption to the Key-Vault.
var client = new KeyVaultClient(GetAccessTokenAsync, new HttpClient());

await client.GetSecretAsync(Constants.Vault.Url, vaultSecretKey);
1
votes

Ok, this is how I got it working, thanks to Dom:

I tried enabling and disabling MSI for the function app several times. Then went to the KeyVault access policy and assigned the required permissions to the corresponding service principal for the function app.

I've also found that assigning the identity with the PowerShell script worked straightaway, so it's probably better than enabling and disabling MSI several times in the portal:

Set-AzureRmWebApp -AssignIdentity $true -Name $webappname -ResourceGroupName myResourceGroup
1
votes

you must have your automation account and the credential account added to your access policy for it to run in a runbook with Powershell. That was news to me. Didn't realize it was 2 accounts vs 1. I kept getting forbidden, just didn't know which accounts needed access.

1
votes

I neglected to grant "List" secrets permission (in addition to "Get" secret). The following issue helped clue me in: https://github.com/aspnet/Extensions/issues/856

0
votes

Also double check your AppId and AppSecret passed to the ClientCredential function. We have multiple key vaults, and the wrong vault credentials were stored in the Azure function application settings.

0
votes

I had a similar issue. I was working in 2 different web browser tabs: one for editing the Azure function app settings, the other to assign the role on the resource. Not sure if it is related, but when I closed the second tab and reconfigured everything from a single tab, things started working properly.

0
votes

I had a similar issue, although I was implementing an App Service instead of Azure Functions.

The cause of my problem was that when I was adding permissions to my Key Vault to allow my App Service to access it (via the Access Policies blade on the Key Vault page), I was mistakenly adding permissions for my App Service instead of my App Service Active Directory app.

When I navigated to "Add New access policy->Select principal" and searched for the name of my App Service, the search results included both items, and choosing the wrong one resulted in "Forbidden" when my App Service code attempted to access the Key Vault. Once I went back and selected the Active Directory item (which includes the word "APPLICATION" once it's added to the list of access policies), the Key Vault worked.