我有一个 Azure Function App,我试图从中提取 Azure Key Vault 的证书。我的代码如下:
private X509Certificate2 GetCertificate(
CertificateClient certificateClient,
SecretClient secretClient,
string certificateName)
{
KeyVaultCertificateWithPolicy certificate = certificateClient.GetCertificate(certificateName);
// Return a certificate with only the public key if the private key is not exportable.
if (certificate.Policy?.Exportable != true)
{
return new X509Certificate2(certificate.Cer);
}
// Parse the secret ID and version to retrieve the private key.
string[] segments = certificate.SecretId.AbsolutePath.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length != 3)
{
throw new InvalidOperationException($"Number of segments is incorrect: {segments.Length}, URI: {certificate.SecretId}");
}
string secretName = segments[1];
string secretVersion = segments[2];
KeyVaultSecret secret = secretClient.GetSecret(secretName, secretVersion);
if ("application/x-pkcs12".Equals(secret.Properties.ContentType, StringComparison.InvariantCultureIgnoreCase))
{
byte[] pfx = Convert.FromBase64String(secret.Value);
// Exception thrown here
return new X509Certificate2(pfx);
}
throw new NotSupportedException($"Only PKCS#12 is supported. Found Content-Type: {secret.Properties.ContentType}");
}
}
我已将 Key Vault 中的访问权限设置为
all
并向该功能添加了额外的日志记录。我可以看到它运行到我评论过的行,并且 pfx
的内容与我添加到 Key Vault 的证书完全匹配。
当尝试创建
X509Certificate2
的实例时,我收到异常 The system cannot find the file specified.
,但没有有关它引用的文件的信息。
奇怪的是,如果使用我的个人 Azure 凭据在本地运行,我会得到完全相同的字节数组,并且不会出现该异常。
系统找不到指定的文件。
要解决此错误,请在
WEBSITE_LOAD_USER_PROFILE=1
中添加应用程序设置 Function App=>Settings=>Configuration/Environment Variables
。请参阅GitHub问题。
将 Key Vault 引用设置为 Function App 中设置的值。
@Microsoft.KeyVault(SecretUri=https://<keyvaultname>.vault.azure.net/certificates/<your_Certificate_name>/)
我的函数应用程序的应用程序设置:
代码片段:
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
string keyVaultUrl = "https://<keyvault>.vault.azure.net/";
string certificateName = "kpcert";
X509Certificate2 certificate ;
var certificateClient = new CertificateClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
var secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
certificate = await GetCertificate(certificateClient, secretClient, certificateName);
log.LogInformation("Certificate retrieved successfully.");
return new OkObjectResult(certificate);
}
private static async Task<X509Certificate2> GetCertificate(
CertificateClient certificateClient,
SecretClient secretClient,
string certificateName)
{
KeyVaultCertificateWithPolicy certificate = await certificateClient.GetCertificateAsync(certificateName);
if (certificate.Policy?.Exportable != true)
{
return new X509Certificate2(certificate.Cer);
}
string[] segments = certificate.SecretId.AbsolutePath.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length != 3)
{
throw new InvalidOperationException($"Number of segments is incorrect: {segments.Length}, URI: {certificate.SecretId}");
}
string secretName = segments[1];
string secretVersion = segments[2];
KeyVaultSecret secret = await secretClient.GetSecretAsync(secretName, secretVersion);
if ("application/x-pkcs12".Equals(secret.Properties.ContentType, StringComparison.InvariantCultureIgnoreCase))
{
byte[] pfx = Convert.FromBase64String(secret.Value);
return new X509Certificate2(pfx);
}
throw new NotSupportedException($"Only PKCS#12 is supported. Found Content-Type: {secret.Properties.ContentType}");
}
控制台输出:
本地响应:
传送门: