Azure Key Vault Operation get is not allowed on a disabled secret

Viewed 863

We have implemented Azure key vault in the .NET core application. Everything is working fine until we disabled the secret from the list - After my application tries to fetch the list again it started giving me the exception

Unhandled exception. Microsoft.Azure.KeyVault.Models.KeyVaultErrorException: Operation get is not allowed on a disabled secret.
   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 Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.LoadAsync()
   at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.Load()
   at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at Microsoft.Extensions.Hosting.HostBuilder.BuildAppConfiguration()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at Vodafone.LandingPage.Program.Main(String[] args) in D:\a\1\s\src\LandingPage\Program.cs:line 30

Code I use to connect with Key Vault in program.cs file.

if (ctx.HostingEnvironment.IsProduction())
{
var builtConfig = builder.Build();

var keyVaultEndpoint = $"https://{builtConfig["AppSettings:KeyVaultName"]}.vault.azure.net/";
   

var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}

How we can restrict the list so that it will not take the disabled secrets together. I am using "Get" and "List" permission.

1 Answers

After a research I found below solution.

You can use it like this

Problem : Code which read all secret

builder.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());

Solution : Code Which read only enabled secrets

builder.AddAzureKeyVault(keyVaultEndpoint,keyVaultClient,new PrefixKeyVaultSecretManager(keyVaultEndpoint));

Implementation of IKeyVaultSecretManager

using System.Collections.Generic;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using Microsoft.Azure.KeyVault;
 using Microsoft.Azure.KeyVault.Models;
 using Microsoft.Azure.Services.AppAuthentication;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Configuration.AzureKeyVault;

namespace KeyVaultPOC
{

public class PrefixKeyVaultSecretManager : IKeyVaultSecretManager
{
    
    private readonly IList<string> _overrides = new List<string>();

    public PrefixKeyVaultSecretManager(string vaultUrl)
    {           

        Task.Run(() => LoadListOfOverrides(vaultUrl)).Wait();
    }

    private async Task LoadListOfOverrides(string vaultUrl)
    {
        var azureServiceTokenProvider = new AzureServiceTokenProvider();
        var keyVaultClient = new KeyVaultClient(
            new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)
        );
                    
        var secrets = await keyVaultClient.GetSecretsAsync(vaultUrl);
        bool moreSecrets;

        do
        {
            foreach (var secret in secrets)
            {                    
                if ((bool)secret.Attributes.Enabled)
                {
                    _overrides.Add(secret.Identifier.Name);
                }
            }

            moreSecrets = !string.IsNullOrEmpty(secrets.NextPageLink);

            if (moreSecrets)
            {
                secrets = await keyVaultClient.GetSecretsNextAsync(secrets.NextPageLink);
            }
        } while (moreSecrets);
    }

    public bool Load(SecretItem secret)
    {
        
        return true;
    }

    public string GetKey(SecretBundle secret)
    {
        var key = secret.SecretIdentifier.Name;

        

        return key;
    }
}

}

Ref : https://gist.github.com/davidxcheng/0576659d2c876d299619d979767dcdd6

Related