首页 > 解决方案 > 无法将证书导入 Keyvault

问题描述

我有以下 powershell 代码,我需要使用这些代码将证书导入密钥库:

###############################################################################

<#
.SYNOPSIS
    Import-KeyVaultCertificate

.DESCRIPTION

    Import-KeyVaultCertificate

.PARAMETER VaultName

.PARAMETER Name

.PARAMETER Password

.PARAMETER Version

.PARAMETER DisableVersions

.NOTES
    This template allows to write secrets into the KeyVault if they are not present. If they are present, the script will ignore it.

.EXAMPLE
    Import-KeyVaultCertificate.ps1 -VaultName 'vaultname' -Name 'certificatename' -Password 'certificatepassword' -Thumbprint 'certificatethumbprint' -FilePath 'certificate.pfx'

.EXAMPLE
    Import-KeyVaultCertificate.ps1 -VaultName 'vaultname' -Name 'certificatename' -SecurePassword (ConvertTo-SecureString -String 'certificatepassword' -AsPlainText -Force) -Thumbprint 'certificatethumbprint' -FilePath 'certificate.pfx'

#>

# ' char inc as Notepad++ language recognition does not like get-help contents
##############################################################################

[CmdletBinding(DefaultParametersetname = "String")]
param (
    [Parameter(Mandatory = $true)]
    [string] $VaultName,
    [Parameter(Mandatory = $true)]
    [string] $Name,
    [Parameter(Mandatory = $true)]
    [string] $Thumbprint,
    [Parameter(Mandatory = $true)]
    [string] $FilePath,
    [Parameter(Mandatory = $true, ParameterSetName = "String")]
    [string] $Password,
    [Parameter(Mandatory = $true, ParameterSetName = "SecureString")]
    [securestring] $SecurePassword,
    [Parameter(Mandatory = $false)]
    [string] $Version,
    [Parameter(Mandatory = $false)]
    [switch] $DisableVersions
)
begin {
    $Verbose = ($PSBoundParameters['Verbose'] -eq $true) -or ($VerbosePreference -eq 'Continue')
    $KeyVaultParams = @{}
    if ($Version -ne $null) {
        $KeyVaultParams.Add('Version', $Version)
    }
}
process {
    try {
        $KeyVault = @(Get-AzureRmResource -ErrorAction Stop | Where-Object {($_.Name -eq $VaultName) -and ($_.ResourceType -eq 'Microsoft.KeyVault/vaults')})
        if ($KeyVault.count -ne 1) {
            Write-Error -Message ('KeyVault "{0}" not found - Internal Error.' -F $VaultName) -ErrorAction Stop
        }
    }
    catch {
        Write-Error -Message ('KeyVault "{0}" not found - Internal Error.' -F $VaultName) -ErrorAction Stop
    }
    $GetKeyVaultCertificate = Get-AzureKeyVaultCertificate -VaultName $VaultName -Name $Name @KeyVaultParams
    if (($GetKeyVaultCertificate -ne $null) -and ($GetKeyVaultCertificate.Name -eq $Name) -and ($GetKeyVaultCertificate.Thumbprint -eq $Thumbprint)) {
        Write-Warning -Message ('Certificate "{0}" with Thumbprint "{1}" is present in KeyVault "{2}"' -F $GetKeyVaultCertificate.Name, $GetKeyVaultCertificate.Thumbprint, $KeyVault.Name)
    }
    elseif (($GetKeyVaultCertificate -eq $null) -or (($GetKeyVaultCertificate -eq $null) -and ($GetKeyVaultCertificate.Thumbprint -ne $Thumbprint))) {
        try {
            $CatchMessage = 'Failed to upload the certificate "{0}" in key vault "{1}".'
            if ($PSCmdlet.ParameterSetName -eq 'String') {
                $SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
            }
            Write-Output ($NewCertValue = Import-AzureKeyVaultCertificate -VaultName $VaultName -Name $Name -Password $SecurePassword -FilePath $FilePath -Verbose:$Verbose -ErrorAction Stop)
            if ($DisableVersions) {
                $CatchMessage = 'Unable to retrieve certificate "{0}" in key vault "{1}".'
                (Get-AzureKeyVaultCertificate -VaultName $VaultName -Name $Name -IncludeVersions | Where-Object {$_.Enabled })  | ForEach-Object {
                    if ($_.Version -ne $NewCertValue.Version) {
                        $CatchMessage = 'Failed to disable version for certificate "{0}" in key vault "{1}" [Version: ' + $_.Version + '].'
                        Set-AzureKeyVaultCertificateAttribute -VaultName $VaultName -Name $Name -Version $_.Version -Enable $false -Verbose:$Verbose -ErrorAction Stop
                    }
                }
            }
        }
        catch {
            Write-Error -Message ($CatchMessage -F $Name, $VaultName) -ErrorAction Stop
        }
    }
}

如果我尝试使用它,它会询问我一个版本,尽管我指定该参数不是强制性的。如果我删除@KeyVaultParams,我会到达 catch 消息中脚本的位置:

'Failed to upload the certificate "{0}" in key vault "{1}".'

对它进行了调试Get-AzureKeyVaultCertificate,我说找不到证书,这是正确的,但它没有转到导入它的行。如果我使用 Import-AzureKeyVaultCertificate -VaultName $VaultName -Name $Name -Password (ConvertTo-SecureString -AsPlainText -Force:$true 'xxxxxx') -FilePath 'cert.pfx'cmdlet 并导入证书,下次我使用脚本时会收到警告 - 这就是我想要的。表示证书在 keyvault 中并且指纹匹配。

所以 2 个问题: 1. 版本似乎是强制性的 - 我该如何解决?2. 如果 keyvault 中不存在证书,则不会导入证书 - 为什么?

谢谢您的帮助

标签: powershellimportcertificateazure-keyvault

解决方案


好的。同时我发现了问题:

  1. @KeyVaultParams- 我删除-eq $null$Version -ne $null
  2. 这里的逻辑是错误的:(($GetKeyVaultCertificate -eq $null) -or (($GetKeyVaultCertificate -eq $null)。它应该是(($GetKeyVaultCertificate -eq $null) -or (($GetKeyVaultCertificate -ne $null)
  3. 当脚本要求输入明文密码时,我将密码解析为安全字符串。
  4. Write-error $_.Exception.Message在最后一个之前添加了一个catch以查看错误,即:The specified network password is not correct.

我希望这可以帮助那些想要以更...花哨的方式导入证书的人:)


推荐阅读