Powershell Azure密钥保险库下载证书(带有私钥)

Powershell Azure密钥保险库下载证书(带有私钥),powershell,certificate,azure-keyvault,Powershell,Certificate,Azure Keyvault,我正在尝试下载我在几个密钥库上拥有的证书,包括它们的私钥。通过Azure Portal,我可以轻松完成此任务,只需转到密钥库,选择证书,然后单击“以PFX/PEM格式下载” 由于我必须在几个钥匙库上重复相同的操作,我一直在寻找一种自动化的方法。到目前为止,我得出以下结论: $objCertificate = (Get-AzKeyVaultCertificate -VaultName <Key Vault> -Name <Certificate Name>).Certifi

我正在尝试下载我在几个密钥库上拥有的证书,包括它们的私钥。通过Azure Portal,我可以轻松完成此任务,只需转到密钥库,选择证书,然后单击“以PFX/PEM格式下载”

由于我必须在几个钥匙库上重复相同的操作,我一直在寻找一种自动化的方法。到目前为止,我得出以下结论:

$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
$objCertificate=(获取AzKeyVaultCertificate-VaultName-Name)。证书
$bytCertificate=$objCertificate.Export('pfx',)
$strCertificate=[System.Convert]::tobase64字符串($bytCertificate)
$strPath=加入路径$env:TEMP“$($objCertificate.Subject).pfx”
$bytCertificate |设置内容-路径$strPath-强制-编码字节
问题是,它只下载带有公钥的证书,我还需要其中包含的私钥,就像我通过门户下载证书一样。
你知道我可能遗漏了什么吗?

要获取私钥,你需要将其作为秘密获取(是的,这很奇怪),我在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}");
        }
    }
}
//
///从Azure密钥库加载证书(带私钥)
///
///获取带有私钥的证书有点困难,但下面的代码解决了这一问题。
/// 
///获取密钥库证书的私钥
/// https://github.com/heaths/azsdk-sample-getcert
/// 
///另请参见以下GitHub问题:
/// https://github.com/Azure/azure-sdk-for-net/issues/12742
/// https://github.com/Azure/azure-sdk-for-net/issues/12083
/// 
/// 
/// 
/// 
公共静态X509Certificate2加载证书(IConfiguration配置,字符串certificateName)
{
字符串vaultUrl=config[“Vault:Url”]??“”;
字符串clientId=config[“Vault:clientId”];
字符串tenantId=config[“Vault:tenantId”];
字符串secret=config[“Vault:secret”];
WriteLine($“正在从Azure密钥库加载证书“{certificateName}”);
var-credentials=new-ClientSecretCredential(tenantId:tenantId,clientId:clientId,clientSecret:secret);
var certClient=new CertificateClient(新Uri(Vault URL)、凭据);
var secretClient=新secretClient(新Uri(Vault URL)、凭据);
var cert=GetCertificateAsync(certClient、secretClient、certificateName);
Console.WriteLine(“已加载证书”);
返回证书;
}
/// 
///获取证书的助手方法
/// 
///来源https://github.com/heaths/azsdk-sample-getcert/blob/master/Program.cs
/// 
/// 
/// 
/// 
/// 
专用静态X509Certificate2 GetCertificateAsync(CertificateClient CertificateClient,
SecretClient SecretClient,
字符串(名称)
{
KeyVault CertificateWithPolicy certificate=certificateClient.GetCertificate(certificateName);
//如果私钥不可导出,则返回仅包含公钥的证书。
if(certificate.Policy?.Exportable!=true)
{
返回新的X509Certificate2(certificate.Cer);
}
//解析机密ID和版本以检索私钥。
string[]segments=certificate.SecretId.AbsolutePath.Split(“/”,StringSplitOptions.RemoveEmptyEntries);
如果(segments.Length!=3)
{
抛出新的InvalidOperationException($“段数不正确:{segments.Length},URI:{certificate.SecretId}”);
}
字符串secretName=段[1];
字符串secretVersion=段[2];
KeyVaultSecret-secret=secretClient.GetSecret(secretName,secretVersion);
//对于PEM,您需要提取base64编码的消息体。
//.NET 5.0预览版引入了System.Security.Cryptography.PemEncoding类以简化此操作。
if(“application/x-pkcs12”.Equals(secret.Properties.ContentType、StringComparison.InvariantCultureInogoreCase))
{
字节[]pfx=Convert.FromBase64String(secret.Value);
返回新的X509Certificate2(pfx);
}
抛出新的NotSupportedException($“仅支持PKCS#12。找到的内容类型:{secret.Properties.ContentType}”);
}
}
}

要获取私钥,您需要将其作为秘密获取(是的,这很奇怪),我在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}");
        }
    }
}
//
///从Azure密钥库加载证书(带私钥)
///
///获取带有私钥的证书有点困难,但下面的代码解决了这一问题。
/// 
///获取密钥库证书的私钥
/// https://github.com/heaths/azsdk-sample-getcert
/// 
///另请参见以下GitHub问题:
/// https://github.com/Azure/azure-sdk-for-net/issues/12742
/// https://github.com/Azure/azure-sdk-for-net/issues/12083
/// 
/// 
/// 
/// 
公共静态X509Certificate2加载证书(IConfiguration配置,字符串certificateName)
{
字符串vaultUrl=config[“Vault:Url”]??“”;
字符串clientId=config[“Vault:clientId”];
字符串tenantId=config[“Vault:tenantId”];
字符串secret=config[“Vault:secret”];
Console.WriteLine($“正在从Azure密钥加载证书“{certificateName}”