ps/Modules/Alkami.DevOps.SystemEngineering/Public/Export-ACMCertificatesByName.ps1
2023-05-30 22:51:22 -07:00

138 lines
5.3 KiB
PowerShell

function Export-ACMCertificatesByName {
<#
.SYNOPSIS
Exports ACM certificates by domain name to the local filesystem.
.DESCRIPTION
Exports ACM certificates by domain name to the local filesystem. Unfortunately, AWS did not accomodate
this use case when they wrote 'Export-ACMCertificate'.
Note that this function may generate more than one set of files because domain name uniqueness is not enforced in ACM.
.PARAMETER DomainName
[string] The domain name of the ACM certificates to retrieve.
.PARAMETER ProfileName
[string] The AWS profile to use during ACM queries.
.PARAMETER Region
[string] The AWS region to use during ACM queries.
.PARAMETER Passphrase
[string] The passphrase to associate with the encrypted exported private key. If not provided, a generated passphrase will be used.
.PARAMETER GeneratePfx
[switch] Flag indicating whether or not the function should generate a PFX file. Note that this functionality requires OpenSSL
to be installed on your machine; if not installed, this flag will result in an error.
.EXAMPLE
Export-ACMCertificatesByName -DomainName '*.sandbox.alkami.net' -Passphrase "Secret" -ProfileName 'temp-prod' -Region 'us-east-1'
.EXAMPLE
Export-ACMCertificatesByName -DomainName '*.sandbox.alkami.net' -ProfileName 'temp-prod' -Region 'us-east-1' -GeneratePfx
.LINK
https://confluence.alkami.com/x/5ILiBg
#>
[CmdletBinding()]
[OutputType([PSObject[]])]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $DomainName,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $ProfileName,
[Parameter(Mandatory = $true)]
[ValidateScript({$_ -in (Get-AWSRegion).region})]
[string] $Region,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string] $Passphrase,
[Parameter(Mandatory = $false)]
[switch] $GeneratePfx
)
$logLead = (Get-LogLeadName)
if ( $GeneratePfx ) {
# Either find OpenSSL or die trying.
$openSslPath = ( Get-Command -Name 'openssl' -CommandType Application -ErrorAction SilentlyContinue -TotalCount 1 ).Source
if ( $null -eq $openSslPath ) {
Write-Error "$logLead : GeneratePfx flag was provided but OpenSSL command was not found on your system. Please install OpenSSL and retry."
return
}
}
# Create the top-level temporary directory.
$tempDir = ( Join-Path ([System.IO.Path]::GetTempPath()) 'CertificateExport' )
New-Item -Path $tempDir -ItemType Directory -Force | Out-Null
# Sanitize the domain name (if necessary).
$pfxDomainName = $DomainName -replace '\*', '_'
$certificateDetailsList = Get-ACMCertificateDetailsListByName -DomainName $DomainName -ProfileName $ProfileName -Region $Region
foreach ( $cert in $certificateDetailsList ) {
Write-Host "$logLead : Processing certificate ARN [$($cert.CertificateArn)]."
if ( $false -eq $PSBoundParameters.ContainsKey( 'Passphrase' ) ) {
$actualPassphrase = New-SecurePassword -PasswordLength 15 -ProfileName $ProfileName -Region $Region
Write-Host "$logLead : Generated passphrase for certificate: $actualPassphrase"
} else {
$actualPassphrase = $Passphrase
}
try {
# Ref: https://docs.aws.amazon.com/powershell/latest/reference/items/Export-ACMCertificate.html
$exportedCert = ( Export-ACMCertificate -CertificateArn $cert.CertificateArn -Passphrase $actualPassphrase.ToCharArray() -ProfileName $ProfileName -Region $Region )
if ( $null -ne $exportedCert ) {
$certDirName = ( $cert.CertificateArn -split '/' )[-1]
$certDir = ( Join-Path $tempDir $certDirName )
$certPath = ( Join-Path $certDir "certificate.pem")
$chainPath = ( Join-Path $certDir "certificate_chain.pem")
$keyPath = ( Join-Path $certDir "private.key")
# Create the temporary directory for this certificate
New-Item -Path $certDir -ItemType Directory -Force | Out-Null
Set-Content -Path $certPath -Value $exportedCert.Certificate -Encoding ASCII
Write-Verbose "$logLead : Generated [$certPath]."
Set-Content -Path $chainPath -Value $exportedCert.CertificateChain -Encoding ASCII
Write-Verbose "$logLead : Generated [$chainPath]."
Set-Content -Path $keyPath -Value $exportedCert.PrivateKey -Encoding ASCII
Write-Verbose "$logLead : Generated [$keyPath]."
if ( $GeneratePfx ) {
$pfxPath = ( Join-Path $certDir "$pfxDomainName.pfx")
Start-Process -FilePath $openSslPath -Wait -argumentlist "pkcs12 -export -out $pfxPath -in $certPath -inkey $keyPath -certfile $chainPath -passin `"pass:$actualPassphrase`" -passout `"pass:$actualPassphrase`""
Write-Verbose "$logLead : Generated [$pfxPath]."
}
Write-Host "$logLead : Files generated at [$certDir]."
}
} catch {
Write-Warning "$logLead : Unable to export ACM certificate ARN [$($cert.CertificateArn)] : $($_.Exception.Message)"
}
}
}