Azure密钥保管库秘密访问间歇性地失败,并出现套接字异常 [英] Azure Key Vault secret access intermittently failing to connect with socket exception

查看:39
本文介绍了Azure密钥保管库秘密访问间歇性地失败,并出现套接字异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行在.NET 4.7.2上并托管在Azure AppService中的MVC 5 Web应用程序,该应用程序使用Azure Key Vault来保存机密.该项目使用 Microsoft.Azure.KeyVault 3.0.3 NuGet程序包,并使用 KeyVaultClient .GetSecretAsync()访问秘密.所有资源都位于同一Azure区域.

I have an MVC 5 web application running on .NET 4.7.2 and hosted in an Azure AppService, that uses Azure Key Vault to hold secrets. The project uses the Microsoft.Azure.KeyVault 3.0.3 NuGet package and the secrets are accessed using the KeyVaultClient and .GetSecretAsync(). All resources are located in the same Azure region.

在大多数情况下,此方法效果很好,并且在90%的时间内,它以毫秒为单位返回秘密.

For the most part this works very well, and for about 90% of the time it returns the secret in milliseconds.

但是,有时访问访问Vault的调用均会失败.这本身并没有表现为SDK引发的异常,但是Web应用程序挂起.最终-通常在1分钟左右,但有时甚至更长的时间-秘密被返回,一切都很好.这是因为SDK使用了重试模式,该模式将继续尝试获取机密.

But every now and then the call to access the Key Vault fails. This doesn't manifest itself as an exception thrown by the SDK, but the web app hangs. Eventually - and normally in around 1 minute but sometimes longer - the secret is returned and all is fine again. This is because the SDK uses a retry pattern, which will keep trying to get the secret.

查看AppService的应用程序见解我可以看到,SDK生成的GET请求从Key Vault获得HTTP 500响应,并抛出SocketException,结果代码为ConnectFailure.

Looking at Application Insights for the AppService I can see that the GET request generated by the SDK gets an HTTP 500 response from the Key Vault and a SocketException is thrown, with a result code of ConnectFailure.

例外是:

查看遥测并逐步执行代码,没有任何共性或明显原因.这似乎是完全随机的.

Looking at the telemetry and stepping through the code there is no element of commonality or obvious cause. It seems to be entirely random.

最重要的是,Azure托管的AppService有时 不能使用最新的框架和SDK版本连接到同一数据中心中的Azure托管的Key Vault.

The bottom line is the Azure hosted AppService sometimes cannot connect to an Azure hosted Key Vault in the same datacentre, using the latest framework and SDK version.

有没有其他人看到或有任何想法?我四处搜寻,发现有人遇到相同问题,但没有人有原因或解决方案.

Has anyone else seen this or have any idea? I've searched around and found a few instances of people experiencing the same issue, but nobody has a cause or solution.

编辑(1):我现在尝试完全在另一个区域中旋转一个新的Key Vault,问题仍然完全相同.

EDIT (1): I have now tried spinning up a new Key Vault in a different region entirely, and the problem remains exactly the same.

推荐答案

我们在项目中遇到了相同的行为,即KeyVault在大多数情况下都是快速可靠的,然后间歇性地停止响应或花费很长时间偶尔返回,没有明显的原因可以解释原因.这种情况发生在我们应用程序的所有层,从API到Azure Functions,再到命令行工具.

We experienced the same behavior on our project, where KeyVault would be fast and reliable most of the time, and then intermittently stop responding or take a very long time to return once in a while with no obvious reason to explain why. This occurred in all tiers of our application, from the API, to Azure Functions, to command line tools.

最终,我们不得不通过在内存中缓存机密来解决此问题,以避免过于频繁地访问KeyVault,而AppSettings类将在内部将其秘密缓存.除此之外,我们还配置了DI容器以将此类视为单例.

Eventually, we had to work around this by caching secrets in memory to avoid hitting the KeyVault too often, where our AppSettings class would cache these internally. In addition to this, we also configured our DI container to treat this class as a singleton.

这是一个非常简化的示例:

Here is a very simplified example:

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 方法也应该进行清理检索到的密钥名称.

This isn't production ready - you'll need to modify this and implement the GetKeyVaultClient method to actually return your KeyVaultClient object, and also the GetSecret method should sanitize the key name being retrieved.

在我们的DI注册表中,我们进行了如下设置以使用单例:

In our DI registry, we had this setup to use a singleton like this:

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

这两个更改似乎对我们来说效果很好,而且我们暂时还没有遇到任何问题.

These two changes seemed to work well for us, and we haven't had any issues with this for a while now.

这篇关于Azure密钥保管库秘密访问间歇性地失败,并出现套接字异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆