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)" } } }