functions/Save-FDKeyVaultCertificate.ps1
function Save-FDKeyVaultCertificate { <# .SYNOPSIS Exports a certificate from Azure KeyVault and stores it in file. .DESCRIPTION Exports a certificate from Azure KeyVault and stores it in file. Supports retrieving the secret information in different format: - Public key information only (.cer) - Encrypted private key information (.pfx) - Unencrypted private key information (.pem) The format is chosen based on the file extension selected for the output file. To save as pfx certificate, specifying a passsword is required. .PARAMETER VaultName Name of the Key Vault to access. .PARAMETER Name Name of the Certificate to save to file. .PARAMETER Path The path to write the certificate to. Include the filename and extension, the extension will determine thee data format retrieved. Supported extensions: .cer, .pfx, .pem .PARAMETER Password The password to protect the certificate with. Only applies to pfx certificates .PARAMETER WhatIf if this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Save-FDKeyVaultCertificate -VaultName myVault -Name myCert -Path .\cert.cer Saves the public key information of the "myCert" certificate in vault "myVault" to the file "cert.cer" in the current folder. .EXAMPLE PS C:\> Save-FDKeyVaultCertificate -VaultName myVault -Name myCert -Path .\cert.pfx -Password (Read-Host -AsSecureString) Saves the "myCert" certificate in vault "myVault" to the file "cert.pfx" in the current folder, protected by the specified password. .EXAMPLE PS C:\> Save-FDKeyVaultCertificate -VaultName myVault -Name myCert -Path .\cert.pem Saves the unencrypted private key information of the "myCert" certificate in vault "myVault" to the file "cert.pem" in the current folder. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory = $true)] [string] $VaultName, [Parameter(Mandatory = $true)] [string] $Name, [Parameter(Mandatory = $true)] [PsfValidateScript('PSFramework.Validate.FSPath.FileOrParent', ErrorString = 'PSFramework.Validate.FSPath.FileOrParent')] [string] $Path, [securestring] $Password ) begin { $outPath = Resolve-PSFPath -Path $Path -Provider FileSystem -NewChild -SingleItem $type = ($outPath -split "\.")[-1] } process { switch ($type) { #region PFX 'pfx' { if (-not $Password) { Stop-PSFFunction -String 'Save-FDKeyVaultCertificate.Error.NoPassword' -Cmdlet $PSCmdlet -EnableException $true } Invoke-PSFProtectedCommand -ActionString 'Save-FDKeyVaultCertificate.Retrieving.Secret' -ActionStringValues $VaultName, $Name -Target $Name -ScriptBlock { $secret = Get-AzKeyVaultSecret -VaultName $VaultName -Name $Name -ErrorAction Stop } -EnableException $true -PSCmdlet $PSCmdlet $certString = [PSCredential]::New("irrelevant", $secret.SecretValue).GetNetworkCredential().Password $bytes = [convert]::FromBase64String($certString) $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes, "", "Exportable,PersistKeySet") $newBytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx, $Password) [System.IO.File]::WriteAllBytes($outPath, $newBytes) } #endregion PFX #region PEM 'pem' { Invoke-PSFProtectedCommand -ActionString 'Save-FDKeyVaultCertificate.Retrieving.Secret' -ActionStringValues $VaultName, $Name -Target $Name -ScriptBlock { $secret = Get-AzKeyVaultSecret -VaultName $VaultName -Name $Name -ErrorAction Stop } -EnableException $true -PSCmdlet $PSCmdlet $certString = [PSCredential]::New("irrelevant", $secret.SecretValue).GetNetworkCredential().Password $bytes = [convert]::FromBase64String($certString) $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes, "", "Exportable,PersistKeySet") $certificatePem = [System.Security.Cryptography.PemEncoding]::Write("CERTIFICATE", $cert.RawData) -join "" $key = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert) $pubKeyPem = [System.Security.Cryptography.PemEncoding]::Write("PUBLIC KEY", $key.ExportSubjectPublicKeyInfo()) -join "" $privKeyPem = [System.Security.Cryptography.PemEncoding]::Write("PRIVATE KEY", $key.ExportPkcs8PrivateKey()) -join "" $certString = $certificatePem, $pubKeyPem, $privKeyPem -join "`n`n" $encoding = [System.Text.UTF8Encoding]::new($false) [System.IO.File]::WriteAllText($outPath, $certString, $encoding) } #endregion PEM #region CER 'cer' { Invoke-PSFProtectedCommand -ActionString 'Save-FDKeyVaultCertificate.Retrieving.Public' -ActionStringValues $VaultName, $Name -Target $Name -ScriptBlock { $cert = Get-AzKeyVaultCertificate -VaultName $VaultName -Name $Name -ErrorAction Stop } -EnableException $true -PSCmdlet $PSCmdlet $bytes = $cert.Certificate.GetRawCertData() [System.IO.File]::WriteAllBytes($outPath, $bytes) } #endregion CER default { Stop-PSFFunction -String 'Save-FDKeyVaultCertificate.Error.UnknownExtension' -StringValues $type, $outPath -Cmdlet $PSCmdlet -EnableException $true } } } } |