Reputation: 3129
I am using IOptions pattern in my Azure function, and I am retrieving Mailjet keys from Azure key vault.
I have created below MailjetConfigOption class:
public class MailjetConfigOption
{
public string PublicKey { get; set; }
public string SecretKey { get; set; }
}
And I have registered in the Startup.cs
[assembly: FunctionsStartup(typeof(Startup))]
namespace Emails.Dispatcher
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddLogging();
builder.Services.AddHttpClient();
builder.Services.AddOptions<MailjetConfigOption>()
.Bind(builder.GetContext().Configuration.GetSection(nameof(MailjetConfigOption)));
}
}
}
Below is my local.settings.json file:
"MailjetConfigOption:PublicKey": "load from key vault",
"MailjetConfigOption:SecretKey": "load from key vault",
Below is my key vault cache class which is added to load secrets from key vault.
public static class KeyVaultCache
{
private const string KeyVaultSettingsUrl = "KeyVaultConfigOption:Url";
private static Dictionary<string, string> SecretsCache = new Dictionary<string, string>();
private static KeyVaultClient _KeyVaultClient = null;
public static KeyVaultClient KeyVaultClient
{
get
{
if (_KeyVaultClient is null)
{
var provider = new AzureServiceTokenProvider();
_KeyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(provider.KeyVaultTokenCallback));
}
return _KeyVaultClient;
}
}
public async static Task<string> GetCachedSecret(string secretName)
{
if (!SecretsCache.ContainsKey(secretName))
{
string baseUri = GetBaseUri();
var secretBundle = await KeyVaultClient.GetSecretAsync($"{baseUri}secrets/{secretName}");
if (!SecretsCache.ContainsKey(secretName))
SecretsCache.Add(secretName, secretBundle.Value);
}
return SecretsCache.ContainsKey(secretName) ? SecretsCache[secretName] : string.Empty;
}
private static string GetBaseUri()
{
string baseUri = Environment.GetEnvironmentVariable(KeyVaultSettingsUrl, EnvironmentVariableTarget.Process);
Ensure.ConditionIsMet(baseUri.IsNotNullOrEmpty(),
() => new InvalidOperationException($"Unable to locate configured {KeyVaultSettingsUrl}"));
return baseUri;
}
Below is MailjetClientFactory
class where I want to use IOptions, but it is loading configurations from local.settings.json instead of key vault, So How Can I retrieve these configurations from key vault? How can i use KeyVaultCache
with MailjetConfigOption
?
public class MailjetClientFactory : IMailjetClientFactory
{
private readonly MailjetConfigOption _mailjetConfigOption;
public MailjetClientFactory(IOptions<MailjetConfigOption> mailjetConfigOption)
{
_mailjetConfigOption = mailjetConfigOption.Value;
}
public IMailjetClient CreateClient()
{
return new MailjetClient(_mailjetConfigOption.PublicKey,
_mailjetConfigOption.SecretKey)
{
Version = ApiVersion.V3_1
};
}
}
Upvotes: 0
Views: 1109
Reputation: 18387
As you're reading using Environment.GetEnvironmentVariable, you can leverage Key Vault Reference which will retrieve the secrets for you.
Steps:
1-add a managed identity to you azure function app
2-add a policy in your Azure key Vault which will grant GET and LIST permission to the managed identity created on step 1
3-Use the key Vault Reference in Azure Function App Settings:
@Microsoft.KeyVault(SecretUri={SECRET_URL})
More Info:
https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references
Upvotes: 1