Exchange 2016: Renew Let's Encrypt certificate

In a previous article I have already described how the free Let's Encrypt certificates can be requested using PowerShell and assigned to the Exchange services.

I am currently working on automating the entire process from requesting the Let's Encrypt certificate to automatic renewal with PowerShell. The goal is a fire-and-forget script for the Exchange certificates, let's see if it works.

In the article linked at the beginning, requesting a certificate via Let's Encrypt already worked. However, the certificates are only valid for 3 months and must therefore be replaced regularly.

I have now tested renewing the certificate using the following script:

Import modules ACMESharp
Import-Modules Webadministration
Add-PSSnapin *exchange*
$PFXPassword = Get-Random -Minimum 1000000 -Maximum 9999999
$CurrentCertThumbprint = (Get-ChildItem -Path IIS:SSLBindings | where {$_.port -match "443" -and $_.IPAddress -match "0.0.0.0" } | select Thumbprint).Thumbprint
$ExchangeCertificate = Get-ExchangeCertificate -Thumbprint $CurrentCertThumbprint
$ExchangeSANs = ($ExchangeCertificate.CertificateDomains).Address
$ExchangeSubject = $ExchangeCertificate.Subject.Replace("CN=","")
if ($ExchangeSANs -notcontains $ExchangeSubject) {$ExchangeSANs += $ExchangeSubject}
$ExchangeSANs
$ExchangeSANID = 1
foreach ($ExchangeSAN in $ExchangeSANs)
{
$CurrentDate = get-date -format ddMMyyyy
$ACMEAlias = "Cert" + "$CurrentDate" + "-" + "$ExchangeSANID"
$ExchangeSANID++
write-host "New Identifier:"
New-ACMEIdentifier -Dns $ExchangeSAN -Alias $ACMEAlias
write-host "Complete Challenge:"
Complete-ACMEChallenge $ACMEAlias -ChallengeType http-01 -Handler iis -HandlerParameters @{ WebSiteRef = 'Default Web Site' }
[Array]$ACMEAliasArray += $ACMEAlias
if ($ExchangeSAN -match $ExchangeSubject) {$ExchangeSubjectAlias = $ACMEAlias}
}
foreach ($ACMEAlias in $ACMEAliasArray)
{
write-host "Submit Challange:"
Submit-ACMEChallenge $ACMEAlias -ChallengeType http-01
}
sleep -seconds 30
foreach ($ACMEAlias in $ACMEAliasArray)
{
write-host "Update:"
Update-ACMEIdentifier $ACMEAlias
}
$SANAlias = "SAN" + "$CurrentDate"
New-ACMECertificate $ExchangeSubjectAlias -Generate -AlternativeIdentifierRefs $ACMEAliasArray -Alias $SANAlias
Submit-ACMECertificate $SANAlias
sleep -seconds 30
Update-ACMECertificate $SANAlias
$CertPath = "$env:temp" + "\" + "$SANAlias" + ".pfx"
Get-ACMECertificate $SANAlias -ExportPkcs12 $CertPath -CertificatePassword $PFXPassword
$ImportPassword = ConvertTo-SecureString -String $PFXPassword -Force -AsPlainText
Import-ExchangeCertificate -FileName $CertPath -FriendlyName $ExchangeSubject -Password $ImportPassword -PrivateKeyExportable:$true | Enable-ExchangeCertificate -Services "SMTP, IMAP, POP, IIS" -force

This script was only used for testing, it does not yet contain any error handling, documentation or similar. The good news: The replacement of the existing Let's Encrypt certificate worked. Here are two screenshots of the script:

Renew Let's Encrypt

Renew Let's Encrypt

I ran the PowerShell as administrator and used the test environment with the original certificate to test the renewal process.

So two important building blocks for the fire-and-forget script are already basically working. But it will still take some time before the tool is ready...

8 thoughts on “Exchange 2016: Let’s Encrypt Zertifikat erneuern”

  1. Funktioniert mit Exchange 2013 wunderbar.

    Hab noch folgendes hinzugefügt, was das alte Certificate löscht und das Certificate in der Site „Exchange Back End“ anpasst, sowie Neustarte der Dienste durchführt.

    Einfach am Ende hinzufügen.

    Ich habe Remove-Item gewählt anstatt Remove-ExchangeCertificate, weil dieser Befehl das Entfernen manchmal nicht zulässt, da dieser nicht erkennt, dass das Zertifikat schon ersetzt worden ist, wenn man den Befehl mehrfach am Tag ausführt.

    $binding = Get-WebBinding -name „Exchange Back End“ -Protocol „https“
    $NewCertThumbprint = (Get-ChildItem -Path IIS:SSLBindings | where {$_.port -match „443“ -and $_.IPAddress -match „0.0.0.0“ } | select Thumbprint).Thumbprint
    $binding.AddSslCertificate($NewCertThumbprint,“my“)
    write-host „Restarting Services“
    iisreset
    Restart-Service MSExchangeUMCR
    Restart-Service MSExchangeUM
    Restart-Service MSExchangeMailboxAssistants
    Get-ChildItem Cert:\LocalMachine\My\$CurrentCertThumbprint | Remove-Item

    Reply
    • Hi Daniel,
      das Exchange Backend Zertifikat muss nicht ausgetauscht werden. Für das Backend bleibt es beim Self Signed Zertifikat.
      Gruß, Frank

      Reply
  2. Hi Franky,

    gibt’s schon was neues in Punkto Exchange 2013 Test ? Weißt du schon mehr ob das Script auch mit dem 2013er funktioniert ?
    Vielen Dank für deine super Beiträge !

    Beste Grüße

    Reply
  3. Jochen Lody kannst du das bitte weiter ausführen?
    „Passen muss für Letsencrypt nur die externe IP“: ich habe es bisher so verstanden, dass das eben nicht ausreicht. Es muss auch das Verzeichnis ‚.well-known‘ verfügbar sein.
    Oder hast du den gesamten Prozess der Zertifikatausstellung auf einem zweiten Webserver ausgeführt? Dann entsteht doch aber zusätzlicher Aufwand um das Zertifikat auf den ‚echten‘ Server zu bringen…

    Reply
  4. Wie gewohnt grandios
    Zur Anmerkung von HHenning.
    Ohne jetzt inhaltlich über das Unbehagen Port 80 zu öffnen zu diskutieren. Mann muss man nicht so unbedingt den Port 80 auf dem Exchange Webserver öffnen. Passen muss für Letsencrypt nur die externe IP. Ich habe, soweit ganz erfolgreich, einen zweiten Webserver benutzt und in der Firewall den Port 80 auf dessen interne IP weitergeleitet. HTTPS geht auf einen anderen. Die Webserver können auf die gleichen Domain Namen antworten.

    Reply
  5. Wahnsinniger Einsatz von Zeit und Gehirnschmalz, danke.
    Was mich nur bei Lets Encrypt stört ist die Tatsache, dass ich den Exchange über Port 80 unverschlüsselt verfügbar machen muss.

    Reply

Leave a Comment