【问题标题】:Get X509 Certificate from Azure Keyvault to use in a REST call从 Azure Keyvault 获取 X509 证书以在 REST 调用中使用
【发布时间】:2020-03-25 17:34:26
【问题描述】:

我正在尝试从 Azure Keyvault 获取证书,然后使用它来调用需要证书进行身份验证的 REST API。

我已尝试在本地执行此操作 - 我在磁盘上有 .pfx 文件,我将其加载到字节数组中,然后从中创建我的证书:

X509Certificate2 x509 = new X509Certificate2(File.ReadAllBytes(path), password);

然后在 RestSharp 中使用该证书进行我的 REST 调用:

IRestClient client = new RestClient(url);
client.ClientCertificates = new X509CertificateCollection { x509 };

var request = new RestRequest(lastUrlPart, Method.GET);
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");

IRestResponse response = client.Execute(request);

if (response.IsSuccessful)
{
    // read out the response and process it
}

像魅力一样工作。

现在我正在尝试做同样的事情,但从 Azure Keyvault 获取证书。我在 Azure AD 中创建了一个应用注册,创建了我的 keyvault,并为我的应用注册的服务标识授予了对 keyvault 的访问权限。我已将证书上传到密钥库中。到目前为止,一切顺利。

我找到了从 Keyvault 获取证书的代码:

var azureServiceTokenProvider = new AzureServiceTokenProvider();

var kv = new KeyVaultClient(async (authority, resource, scope) =>
                                        {
                                            var authContext = new AuthenticationContext(authority, TokenCache.DefaultShared);
                                            var clientCred = new ClientCredential(clientAppId, clientSecret);
                                            var result = await authContext.AcquireTokenAsync(resource, clientCred);

                                            if (result == null)
                                            {
                                                throw new InvalidOperationException("Failed to obtain the JWT token");
                                            }

                                            return result.AccessToken;
                                        });

string certIdentifier = "https://mykeyvault.vault.azure.net/certificates/Certificate-TEST/14753af7586445fe9d57efa136ac090c";

var vaultCertificate = kv.GetCertificateAsync(certIdentifier).GetAwaiter().GetResult();

这也有效 - 我可以使用我的应用程序身份访问 keyvault,我可以从 keyvault 获取证书,并且 X.509 指纹是有效的 - 但现在这是来自 Microsoft.Azure.KeyVault.Models 命名空间的 CertificateBundle - 如何将其“转换”为“常规”X509Certificate2 对象,以便可以将其用于 REST 调用?

例如,我已经尝试了几件事

X509Certificate2 x509 = new X509Certificate2(vaultCertificate.Cer);

但没有任何效果 - 当我进行 REST 调用时,我收到 HTTP 403 - Forbidden 错误返回......

我错过了什么?如何从 Azure Keyvault 获取可用于在后续 REST 调用中进行身份验证的格式的证书??

【问题讨论】:

    标签: rest x509certificate azure-keyvault


    【解决方案1】:

    当然 - 在我发布这个问题之后,我偶然发现了解决方案....

    这个blog post by Matt Small 非常详细地解释了它(并且还提供了非常好的工作代码示例)。

    基本上,为了使用证书进行身份验证,您也需要拥有私钥 - 当您执行GetCertificateAsync 时,您只能取回证书的公开信息。

    您需要获取证书作为机密,然后对其进行 base64 解码 - 然后获得所有必要的位,REST 调用就可以工作了。

    天哪!怎么这么纠结??为什么不能在 GetCertificateAsync 调用中只使用 includePrivate: bool 参数来告诉 Keyvault 您是否只需要证书的公共部分或公共私有部分?

    您存储了一个证书 - 但要获得它,您需要获取一个秘密......这是完全错误的,并且违反了最小意外的基本原则! MS,如果你是聆听 - 这个 API 确实需要更多的工作才能让 Azure 开发新手更容易上手!!

    还有 PS:这当然也意味着您用来访问密钥库的用户/身份现在需要权限才能读取机密 - 而不仅仅是证书.....

    【讨论】:

    • 嘿,太好了。我自己偶然发现了这个问题,并且可以一直跟随你这个API。
    【解决方案2】:

    试试下面的代码:

    var cert = kvc.GetCertificateAsync(baseUrl, "Demo").ConfigureAwait(false).GetAwaiter().GetResult();
    var cert_content = cert.Cer;
    X509Certificate2 x509 = new X509Certificate2(cert_content);
    

    您可以从CertificateBundle 轻松获取证书的原始字节,然后使用原始字节创建您的 X509Certificate2 实例。

    【讨论】:

    • 我自己也试过了(这也是我帖子的一部分)-但是没有工作-看我的回复-这是要走的路。跨度>
    • 看来你需要私钥。但是,您只能从 Azure Key Vault 证书中检索公共证书。
    • 所以,唯一的解决方案应该是使用secret来存储整个pfx文件内容,然后获取它并使用它来创建一个X509Certificate2对象。
    • 证书作为 证书 存储在 Azure Keyvault 中 - 但您必须作为机密检索 以获得公共和私有组件其中。我知道 - 很奇怪而且不是很清楚 - 我希望 MS 正在倾听并改进这个 Keyvault 客户端 API!
    • 是的。我也这么认为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 1970-01-01
    • 2021-07-04
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    相关资源
    最近更新 更多