我們已經使用WebJobs SDK中的[FunctionName]
屬性在類中定義了一些Azure函數。該類有幾個功能,他們都需要訪問存儲在Azure KeyVault中的祕密。問題是我們每分鐘都有數百次的函數調用,並且由於每個函數都在調用KeyVault,因此KeyVault失敗時會顯示一條消息,如「連接太多,通常只允許10個連接」。Azure KeyVault - 來自Azure函數的太多連接
@crandycodes
(Chris Anderson)在Twitter上建議使KeyVaultClient
爲靜態。但是,我們用於KeyVaultClient
的構造函數需要構造函數的委託函數,並且不能將靜態方法用作委託。那麼我們如何才能使KeyVaultClient
爲靜態?這應該允許功能共享客戶端,從而減少套接字的數量。
下面是我們的KeyVaultHelper
類:
public class KeyVaultHelper
{
public string ClientId { get; protected set; }
public string ClientSecret { get; protected set; }
public string VaultUrl { get; protected set; }
public KeyVaultHelper(string clientId, string secret, string vaultName = null)
{
ClientId = clientId;
ClientSecret = secret;
VaultUrl = vaultName == null ? null : $"https://{vaultName}.vault.azure.net/";
}
public async Task<string> GetSecretAsync(string key)
{
try
{
using (var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenAsync),
new HttpClient()))
{
var secret = await client.GetSecretAsync(VaultUrl, key);
return secret.Value;
}
}
catch (Exception ex)
{
throw new ApplicationException($"Could not get value for secret {key}", ex);
}
}
public async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority, TokenCache.DefaultShared);
var clientCred = new ClientCredential(ClientId, ClientSecret);
var result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
throw new InvalidOperationException("Could not get token for vault");
}
return result.AccessToken;
}
}
下面是我們如何引用我們的功能類:
public class ProcessorEntryPoint
{
[FunctionName("MyFuncA")]
public static async Task ProcessA(
[QueueTrigger("queue-a", Connection = "queues")]ProcessMessage msg,
TraceWriter log
)
{
var keyVaultHelper = new KeyVaultHelper(CloudConfigurationManager.GetSetting("ClientId"), CloudConfigurationManager.GetSetting("ClientSecret"),
CloudConfigurationManager.GetSetting("VaultName"));
var secret = keyVaultHelper.GetSecretAsync("mysecretkey");
// do a stuff
}
[FunctionName("MyFuncB")]
public static async Task ProcessB(
[QueueTrigger("queue-b", Connection = "queues")]ProcessMessage msg,
TraceWriter log
)
{
var keyVaultHelper = new KeyVaultHelper(CloudConfigurationManager.GetSetting("ClientId"), CloudConfigurationManager.GetSetting("ClientSecret"),
CloudConfigurationManager.GetSetting("VaultName"));
var secret = keyVaultHelper.GetSecretAsync("mysecretkey");
// do b stuff
}
}
我們可以使KeyVaultHelper
類的靜態,但反過來就需要一個靜態KeyVaultClient
對象,以避免在每個函數調用上創建新的連接 - 那麼我們該怎麼做,或者有另一種解決方案?我們無法相信需要KeyVault訪問的功能不可擴展!?
感謝@Peter - 我們結束做這樣的事情。可惜的是,你無法擴展需要KeyVault的函數 - 看起來有點棘手的問題。 MemCache感覺很糟糕。 –