powershell - 带有私钥的 Azure Key Vault 下载证书
问题描述
我正在尝试下载我在多个 KeyVault 上拥有的证书,包括它们的私钥。通过 Azure 门户,我可以毫无问题地前往KeyVault,选择证书并单击“以 PFX/PEM 格式下载”
由于我必须在几个 keyvaults 上重复相同的操作,所以我正在寻找一种自动化的方式来完成它。到目前为止,我得出以下结论:
$objCertificate = (Get-AzKeyVaultCertificate -VaultName <Key Vault> -Name <Certificate Name>).Certificate
$bytCertificate = $objCertificate.Export('pfx',<Password>)
$strCertificate = [System.Convert]::ToBase64String($bytCertificate)
$strPath = Join-Path $env:TEMP "$($objCertificate.Subject).pfx"
$bytCertificate | Set-Content -Path $strPath -Force -Encoding Byte
问题是它仅使用公钥下载证书,并且我还需要包含在其中的私钥,就像我通过门户下载它时一样。你知道我可能会错过什么吗?
解决方案
要获取私钥,您需要将其作为秘密(是的,这很奇怪),我在 PowerShell 中没有答案,但我希望我下面的 C# 代码可以为您提供一些有关如何操作的提示。
/// <summary>
/// Load a certificate (with private key) from Azure Key Vault
///
/// Getting a certificate with private key is a bit of a pain, but the code below solves it.
///
/// Get the private key for Key Vault certificate
/// https://github.com/heaths/azsdk-sample-getcert
///
/// See also these GitHub issues:
/// https://github.com/Azure/azure-sdk-for-net/issues/12742
/// https://github.com/Azure/azure-sdk-for-net/issues/12083
/// </summary>
/// <param name="config"></param>
/// <param name="certificateName"></param>
/// <returns></returns>
public static X509Certificate2 LoadCertificate(IConfiguration config, string certificateName)
{
string vaultUrl = config["Vault:Url"] ?? "";
string clientId = config["Vault:ClientId"] ?? "";
string tenantId = config["Vault:TenantId"] ?? "";
string secret = config["Vault:Secret"] ?? "";
Console.WriteLine($"Loading certificate '{certificateName}' from Azure Key Vault");
var credentials = new ClientSecretCredential(tenantId: tenantId, clientId: clientId, clientSecret: secret);
var certClient = new CertificateClient(new Uri(vaultUrl), credentials);
var secretClient = new SecretClient(new Uri(vaultUrl), credentials);
var cert = GetCertificateAsync(certClient, secretClient, certificateName);
Console.WriteLine("Certificate loaded");
return cert;
}
/// <summary>
/// Helper method to get a certificate
///
/// Source https://github.com/heaths/azsdk-sample-getcert/blob/master/Program.cs
/// </summary>
/// <param name="certificateClient"></param>
/// <param name="secretClient"></param>
/// <param name="certificateName"></param>
/// <returns></returns>
private static X509Certificate2 GetCertificateAsync(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('/', 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);
// For PEM, you'll need to extract the base64-encoded message body.
// .NET 5.0 preview introduces the System.Security.Cryptography.PemEncoding class to make this easier.
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}");
}
}
}
推荐阅读
- mysql - 如何将 3 个查询合并为 1 个
- reactjs - 当数据值为空时,React Native 下拉菜单不起作用
- google-drive-api - 合并从 Google Drive 下载的拆分 zip 文件
- python - 如何修复 TypeError:'float' 对象不可调用
- python - 通过嵌套的 JSON 键解析
- azure - Azure Databricks 在 Azure GovCloud 中可用吗?
- c# - 找不到任何已安装的 .NET Core SDK
- java - 这个日期时间格式是什么?如何将其转换为人类可读的输出?为什么它返回这个输出?
- mysql - SQL Order 表按 group_concatenated 列,大多数结果为空
- machine-learning - 这个问题是分类还是回归?