6
votes

I'm trying to access KeyVault from an .net Core console application, using a Service Principle (I have the App Id and App Secret). Here's my code:

var client = new KeyVaultClient(GetAccessToken);
var secret = client.GetSecretAsync("https://{keyvaultName}.vault.azure.net", "MySecret").Result; 

Which calls back to this function:

private static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
    var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
    var credential = new ClientCredential(clientId: appId, clientSecret: appSecret);

    var authResult = await context.AcquireTokenAsync(resource, credential);
    return authResult.AccessToken;
}

Calling GetSecretAsync returns an "AccessDenied" exception. Modifying the code to use this callback yeilds an "Unauthorized" exception:

private static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
    var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
    var credential = new ClientCredential(clientId: appId, clientSecret: appSecret);

    **var authResult = await context.AcquireTokenAsync("https://management.core.windows.net/", credential);**
    return authResult.AccessToken;
}

I setup the Service Principle by going to Azure > AAD > App Registrations, noted the App Id and password (App Secret) when I setup the Principle.

Then in KeyVault, I added the principle to Access Control (IAM), with contributor rights, but still no joy!

Has anyone come across this scenario before?

Thanks! :)

2

2 Answers

7
votes

I test it with the following code, it works correctly on my side. The resourceUri is https://vault.azure.net.

static string appId = "xxxxxxxxxxxxx";
static string appSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
static string tenantId = "xxxxxxxxxxxxxxxxxxxxx";
public static void Main(string[] args)
{
    var kv = new KeyVaultClient(GetAccessToken);
    var scret = kv.GetSecretAsync("https://xxxxxx.vault.azure.net", "secretname").GetAwaiter().GetResult();
}

public static async Task<string> GetAccessToken(string azureTenantId, string clientId, string redirectUri)
{
    var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
    var credential = new ClientCredential(appId, appSecret);
    var tokenResult = await context.AcquireTokenAsync("https://vault.azure.net", credential);
   return tokenResult.AccessToken;
}

Also, you need to add permission with "Key Vault" to the registered app. enter image description here

In Key vault channel, you need to Add policies to your registered application or user. And in Access Control you need to add permission to your registered application or user. enter image description here enter image description here

The output is as below:enter image description here

3
votes

"Access Control (IAM)" controls access to the vault itself. There is a separate way to control access to the contents of the vaults (i.e.: the keys, secrets, and certificates). As mentioned in these docs, we can authorize a given AAD application to retrieve secrets in a given vault in the Azure Portal by navigating to the desired vault, selecting "Access policies", clicking on "Add new", and then searching for your service principal. You should be able to filter by application ID:

enter image description here enter image description here