访问Azure密钥保管库时出现客户端证书例外

时间:2019-09-16 10:40:37

标签: azure asp.net-core client-certificates azure-keyvault

这一天让我忙了一天。

我正在尝试使用经过认证的安全性从.net core 2.2应用程序中使用Azure Key Vaults服务。

我将在应用程序启动时使用相同的代码安装证书,并使用base64编码的字符串作为输入参数。

StoreLocation.LocalMachine中安装(并以admin身份运行VS)时,该应用程序可以正常运行,并且可以检索秘密。

使用StoreLocation.CurrentUser时,应用程序在尝试从Vault检索机密时会抛出NullReferenceException

   at Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.SignWithCertificate(String message, X509Certificate2 certificate)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.JsonWebToken.Sign(IClientAssertionCertificate credential)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey.AddToParameters(IDictionary`2 parameters)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<SendTokenRequestAsync>d__64.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<RunAsync>d__55.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext
....

我曾经看到人们在2017年迁移到.NET 4.7时曾提到过相同类型的异常 (HereHere)。

我尝试使用Microsoft.IdentityModel.Clients.ActiveDirectory软件包的各种较新版本运行该应用程序,但未成功。从3.14到3.19,它将引发相同的异常。从4.3开始,它缺少软件包不再提供的.Platforms dll。

最后,我从Extensions repository中获取,编译并运行了示例应用程序(该应用程序也使用CurrentUser位置,并且我有相同的例外。

我尚未尝试在.NET Core 3.0上运行它。但是我相信最初的写作是有问题的。

我没有足够的资源来进行调查,因此我正在与社区联系:)

下面是作为用于编写/读取证书的简单示例应用程序的代码。

dotnet .\Certificates.dll -- -c {cert-base64-encoded-string} -p {cert-password}
public static Main(string[] args)
{
    //// Using CommandLineParser
    var options = Parser.Default.ParseArguments<Options>(args)
        .WithParsed(o =>
        {
            if (!string.IsNullOrEmpty(o.Certificate))
            {
                o.CertPassword = o.CertPassword ?? throw new ArgumentNullException("No certificate password provided.");

                var rawData = Convert.FromBase64String(o.Certificate);

                //// install certificate
                using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite))
                {
                    var cert = new X509Certificate2(rawData, o.CertPassword, X509KeyStorageFlags.PersistKeySet);
                    ThumbPrint = cert.Thumbprint;
                    store.Add(cert);
                }
            }
        });

    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(configHost =>
        {
            using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
            {
                store.Open(OpenFlags.ReadOnly);

                var certs = store.Certificates.Find(X509FindType.FindByThumbprint, ThumbPrint, false);

                configHost.AddAzureKeyVault(_vault, _key, certs.OfType<X509Certificate2>().Single());

            }
        })
        .UseStartup<Startup>();

1 个答案:

答案 0 :(得分:0)

在为这个问题的示例编写GitHub readme文件时,我偶然发现了解决方案。

我很难说这是人为错误...

我为证书传递了错误的Base64String。可能是我之前创建的。

在命令中传递正确的生成字符串时,代码开始工作。您可以在我的GitHub

上看到它

简而言之,它失败了,因为我在客户端上使用的证书与服务器上的证书不对应。虽然例外可能更清楚。