我有一个在.NET 4.7.2上运行并托管在Azure AppService中的MVC 5 Web应用程序,该应用程序使用Azure Key Vault来保存机密.该项目使用Microsoft.Azure.KeyVault 3.0.3 NuGet程序包,并使用KeyVaultClient和.GetSecretAsync()访问秘密.所有资源都位于同一Azure区域中.
在大多数情况下,此方法效果很好,并且在90%的时间内,它以毫秒为单位返回秘密.
但是,访问该金库的调用有时会失败.这本身并没有表现为SDK引发的异常,但是Web应用程序挂起.最终-通常在1分钟左右,但有时甚至更长的时间-秘密被返回,一切都很好.这是因为SDK使用重试模式,它将继续尝试获取机密.
查看AppService的应用程序见解,我可以看到SDK生成的GET请求从Key Vault获得HTTP 500响应,并抛出SocketException,其结果代码为ConnectFailure.
例外是:
查看遥测并逐步执行代码,没有任何共同点或明显原因.这似乎是完全随机的.
最重要的是,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] 举报,一经查实,本站将立刻删除。