c#-Azure密钥保管库秘密访问间歇性地失败,并出现套接字异常

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

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

Working Key Vault Access

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

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

Exception

例外是:

Exception

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

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

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

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

解决方法:

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

最终,我们不得不通过在内存中缓存机密来解决此问题,以避免过于频繁地访问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();

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐