通过 IKeyVaultClient.GetCertificateAsync 检索时,Azure Key Vault 证书没有私钥

Azure Key Vault Certificates does not have the Private Key when retrieved via IKeyVaultClient.GetCertificateAsync

我有 2 种方法来做同样的事情,但 Azure 已弃用一种有效的方法,另一种方法无效。

有效但已弃用的方法:

我将我的 PFX 存储在 Azure Key Vault Secrets 中。 (当我创建秘密时,我看到一条警告,指出此功能已弃用)

并使用以下代码检索它以创建我的证书:

        SecretBundle secret = await keyVaultClient.GetSecretAsync(keyVaultUrl, "MyCert-Secret");
        X509Certificate2Collection exportedCertCollection = new X509Certificate2Collection();
        exportedCertCollection.Import(Convert.FromBase64String(secret.Value));
        X509Certificate2 certFromSecret = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);

感谢

我能够使用此证书成功托管和访问我的应用程序。

这种方法行不通,但我应该使用:

我将我的证书存储在 Azure 密钥保管库中 证书

并使用以下代码检索它并创建 X509Certificate2:

        CertificateBundle certificateBundle = await keyVaultClient.GetCertificateAsync(keyVaultUrl, "MyCert-Certificate");
        X509Certificate2 certFromCertificate = new X509Certificate2(certificateBundle.Cer);

这种方法的问题是证书不包含私钥。即 certFromCertificate.HasPrivateKey 是错误的。

我的问题

为什么 certFromSecret 有私钥,而 certFromCertificate 没有?

如何从密钥保管库中检索证书,我可以在密钥保管库中创建 X509Certificate2 对象以使用 UseHttps 在 Kestrel 中托管我的应用程序。

@Adrian 的第 2 部分 很好地解释了 Azure KV 证书的概念,我已经更改了我的代码如下以获得包括私钥的完整证书:

        SecretBundle secret = await kv.GetSecretAsync(keyVaultUrl, certName);
        X509Certificate2 certificate = 
                 new X509Certificate2(Convert.FromBase64String(secret.Value));

诀窍是使用 GetSecretAsync 而不是 GetCertificateAsync。请参考 Adrian 的 以了解为什么必须使用秘密来获取带有私钥的完整证书。

请注意,您应该使用 Azure 证书的 属性 页面中的 "Certificate identifier" 属性(url 和“/secrets/”)。

最新版本的SDK(Azure.Security.KeyVault.Certificates 4.2.0)现在有DownloadCertificateAsync方法,可以直接获取完整的证书(即私钥)。

文档指出:

Because Cer contains only the public key, this method attempts to download the managed secret that contains the full certificate.

X509Certificate2 cert = await certificateClient.DownloadCertificateAsync(certName);