从 Azure Keyvault 获取 X509 证书以在 REST 调用中使用
Get X509 Certificate from Azure Keyvault to use in a REST call
我正在尝试从 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 中获取证书:
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();
这也有效——我可以用我的应用身份访问密钥库,我可以从密钥库获取证书,X.509 指纹有效——但现在这是一个 CertificateBundle
来自Microsoft.Azure.KeyVault.Models
命名空间 - 如何将其 "convert" 放入 "regular" X509Certificate2
对象中,以便我可以将其用于 REST 调用?
我试过很多东西,例如
X509Certificate2 x509 = new X509Certificate2(vaultCertificate.Cer);
但没有任何效果 - 当我发出 REST 调用时,我收到 HTTP 403 - 禁止错误返回....
我错过了什么??如何以可用于在后续 REST 调用中进行身份验证的格式从 Azure Keyvault 获取证书?
当然 - 在我发布这个问题之后,我偶然发现了解决方案....
这个 blog post by Matt Small 非常详细地解释了它(并且非常好,并且 工作 代码示例也是如此)。
基本上,为了使用证书进行身份验证,您还需要有私钥 - 当您执行 GetCertificateAsync
时,您只会得到 public 信息证书.
您需要获取证书作为秘密,然后对其进行 base64 解码 - 然后您获得所有必要的位,REST 调用就可以工作了。
天啊!为什么这如此令人费解?为什么在 GetCertificateAsync
调用中不能只有一个 includePrivate: bool
参数来告诉 Keyvault 您是否只需要 public 或 public 和 你证书的隐私部分?
您存储了一个证书 - 但要获取它,您需要获取一个秘密....那是完全错误的,并且违反了最不意外的基本原则! MS ,如果你在听 - 这个 API 确实需要做更多的工作才能让 Azure 开发新手更容易上手!!
和PS:这当然也意味着您用来访问密钥库的user/identity现在需要权限来读取机密——而不仅仅是证书......
试试下面的代码:
var cert = kvc.GetCertificateAsync(baseUrl, "Demo").ConfigureAwait(false).GetAwaiter().GetResult();
var cert_content = cert.Cer;
X509Certificate2 x509 = new X509Certificate2(cert_content);
您可以轻松地从 CertificateBundle
获取证书的原始字节,然后使用原始字节创建您的 X509Certificate2 实例。
我正在尝试从 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 中获取证书:
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();
这也有效——我可以用我的应用身份访问密钥库,我可以从密钥库获取证书,X.509 指纹有效——但现在这是一个 CertificateBundle
来自Microsoft.Azure.KeyVault.Models
命名空间 - 如何将其 "convert" 放入 "regular" X509Certificate2
对象中,以便我可以将其用于 REST 调用?
我试过很多东西,例如
X509Certificate2 x509 = new X509Certificate2(vaultCertificate.Cer);
但没有任何效果 - 当我发出 REST 调用时,我收到 HTTP 403 - 禁止错误返回....
我错过了什么??如何以可用于在后续 REST 调用中进行身份验证的格式从 Azure Keyvault 获取证书?
当然 - 在我发布这个问题之后,我偶然发现了解决方案....
这个 blog post by Matt Small 非常详细地解释了它(并且非常好,并且 工作 代码示例也是如此)。
基本上,为了使用证书进行身份验证,您还需要有私钥 - 当您执行 GetCertificateAsync
时,您只会得到 public 信息证书.
您需要获取证书作为秘密,然后对其进行 base64 解码 - 然后您获得所有必要的位,REST 调用就可以工作了。
天啊!为什么这如此令人费解?为什么在 GetCertificateAsync
调用中不能只有一个 includePrivate: bool
参数来告诉 Keyvault 您是否只需要 public 或 public 和 你证书的隐私部分?
您存储了一个证书 - 但要获取它,您需要获取一个秘密....那是完全错误的,并且违反了最不意外的基本原则! MS ,如果你在听 - 这个 API 确实需要做更多的工作才能让 Azure 开发新手更容易上手!!
和PS:这当然也意味着您用来访问密钥库的user/identity现在需要权限来读取机密——而不仅仅是证书......
试试下面的代码:
var cert = kvc.GetCertificateAsync(baseUrl, "Demo").ConfigureAwait(false).GetAwaiter().GetResult();
var cert_content = cert.Cer;
X509Certificate2 x509 = new X509Certificate2(cert_content);
您可以轻松地从 CertificateBundle
获取证书的原始字节,然后使用原始字节创建您的 X509Certificate2 实例。