簡體   English   中英

Azure Key Vault 秘密訪問間歇性地無法連接,出現套接字異常

[英]Azure Key Vault secret access intermittently failing to connect with socket exception

我有一個在 .NET 4.7.2 上運行並托管在 Azure AppService 中的 MVC 5 Web 應用程序,它使用 Azure Key Vault 來保存機密。 該項目使用Microsoft.Azure.KeyVault 3.0.3 NuGet 包,並且使用KeyVaultClient.GetSecretAsync()訪問機密。 所有資源都位於同一個 Azure 區域。

在大多數情況下,這非常有效,並且在大約 90% 的時間里,它以毫秒為單位返回秘密。

工作 Key Vault 訪問

但訪問 Key Vault 的調用時不時會失敗。 這不會表現為 SDK 拋出的異常,而是 Web 應用程序掛起。 最終——通常在 1 分鍾左右,但有時會更長——秘密被返回,一切又好起來了。 這是因為 SDK 使用重試模式,它將不斷嘗試獲取秘密。

查看 AppService 的 Application Insights,我可以看到 SDK 生成的 GET 請求從 Key Vault 獲取 HTTP 500 響應並拋出 SocketException,結果代碼為 ConnectFailure。

例外

例外是:

例外

查看遙測和單步執行代碼,沒有共同點或明顯原因。 這似乎是完全隨機的。

底線是 Azure 托管的 AppService有時無法使用最新的框架和 SDK 版本連接到同一數據中心中的 Azure 托管的 Key Vault。

有沒有其他人看到這個或有任何想法? 我四處搜索,發現有幾個人遇到了同樣的問題,但沒有人有原因或解決方案。

編輯(1):我現在嘗試在完全不同的區域啟動一個新的 Key Vault,問題仍然完全相同。

我們在項目中遇到了相同的行為,其中KeyVault在大多數時間內都是快速可靠的,然后間歇性地停止響應或者花費很長時間偶爾返回,沒有明顯的理由解釋原因。 這發生在我們的應用程序的所有層中,從API,Azure函數到命令行工具。

最終,我們不得不通過在內存中緩存秘密來解決這個問題,以避免過於頻繁地訪問KeyVault,我們的AppSettings類會在內部緩存它們。 除此之外,我們還配置了DI容器,將此類視為單例。

這是一個非常簡單的例子:

public class MyAppSettings : IAppSettings
{
    private readonly ObjectCache _cache = MemoryCache.Default;
    private readonly object _lock = new Object();
    private KeyValueClient _kvClient;

    public string MySecretValue => GetSecret("MySecretValue");

    private KeyValueClient GetKeyVaultClient()
    {
        // Initialize _kvClient if required

        return _kvClient;
    }

    private string GetSecret(string name)
    {
        lock (_lock)
        {
            if (_cache.Contains(key))
                return (string) _cache.Get(key);

            // Sanitize name if required, remove reserved chars

            // Construct path
            var path = "...";

            // Get value from KV

            var kvClient = GetKeyVaultClient();
            Task<SecretBundle> task = Task.Run(async() => await kvClient.GetSecretAsync(path));

            var value = task.Result;

            // Cache it
            _cache.Set(name, value, DateTime.UtcNow.AddHours(1));

            return value;
        }
    }
}

這不是生產准備 - 您需要修改它並實現GetKeyVaultClient方法以實際返回KeyVaultClient對象,並且GetSecret方法還應清理正在檢索的密鑰名稱。

在我們的DI注冊表中,我們有這樣的設置使用這樣的單例:

For<IAppSettings>().Use<MyAppSettings>().Singleton();

這兩個變化對我們來說似乎很有效,而且我們暫時沒有遇到任何問題。

另一種選擇是將密鑰庫中的機密作為部署管道中的應用設置部署到您的應用服務應用程序。

優點:

  • 將秘密置於源代碼控制之外
  • 刪除對密鑰庫的運行時依賴
  • 更快可靠的本地訪問機密

缺點:

  • 更新機密需要重新部署

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM