Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Automatically renews LetsEncrypt certifications in IIS using Powershell and ACMESharp.
###
#
# update_letsencrypt.ps1
#
# Adds or renews an SSL certificate for listed IIS websites using the ACMESharp Powershell
# modules (https://github.com/ebekker/ACMESharp) and AWS Route53 for DNS management
# (https://aws.amazon.com/powershell/). If the script is scheduled it must be run as
# the local administrator account with the highest privileges. The LetsEncrypt vault should
# already be initialized. The $sites variable lists the alias, IIS configuration
# hostname for SNI if used, and the FQDN used for DNS verification. The primary purpose is
# to schedule this script to run every other month or so to renew existing sites/certificates.
#
###
# Variables
$today = Get-Date -Format yyyyMMdd
$certDir = "C:\certs\"
$awsZoneId = "1234567890"
$sites = @(
@{alias = "web-uat-$today"; ip = ""; hostname = "web.uat.mysite.com"; dns = "web.uat.mysite.com"},
@{alias = "web-prod-$today"; ip = "10.10.3.56"; hostname = ""; dns = "prod.mysite.com"}
)
Import-Module WebAdministration
Import-Module ACMESharp
Import-Module "C:\Program Files (x86)\AWS Tools\PowerShell\AWSPowerShell\AWSPowerShell.psd1"
foreach ($s in $sites) {
New-ACMEIdentifier -Dns $s.dns -Alias $s.alias
$challenge = Complete-ACMEChallenge $s.alias -ChallengeType dns-01 -Handler manual
$dnsName = ($challenge.Challenges | Where-Object {$_.Type -eq "dns-01"}).Challenge.RecordName
$dnsValue = ($challenge.Challenges | Where-Object {$_.Type -eq "dns-01"}).Challenge.RecordValue
# With our DNS challenge, update/create the Route53 record
$dnsChange = New-Object Amazon.Route53.Model.Change
$dnsChange.Action = "UPSERT"
$dnsChange.ResourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
$dnsChange.ResourceRecordSet.Name = $dnsName
$dnsChange.ResourceRecordSet.Type = "TXT"
$dnsChange.ResourceRecordSet.TTL = 3600
$dnsChange.ResourceRecordSet.ResourceRecords.Add(@{Value="`"$dnsValue`""})
$changedSet = Edit-R53ResourceRecordSet -HostedZoneId $awsZoneId -ChangeBatch_Change $dnsChange
$changedSetStatus = $changedSet.Status
while ($changedSetStatus -ne "INSYNC") {
Sleep 20
$changedSetStatus = (Get-R53Change -Id $changedSet.Id).Status
}
# With the DNS change complete, validate our domain
Submit-ACMEChallenge $s.alias -ChallengeType dns-01
$identifier = Update-ACMEIdentifier $s.alias
while ($identifier.Status -ne "valid") {
Sleep 20
$identifier = Update-ACMEIdentifier $s.alias
}
# Identifer is set, create the cert
$certPath = $certDir + $s.alias + ".pfx"
$binding = $s.ip + "!443"
$sniEnabled = 0
if ($s.hostname) {
$binding += "!" + $s.hostname
$sniEnabled = 1
}
New-ACMECertificate $s.alias -Generate -Alias $s.alias
Submit-ACMECertificate $s.alias
$certIdentifier = Update-ACMECertificate $s.alias
while ($certIdentifier.IssuerSerialNumber -eq $null) {
Sleep 20
$certIdentifier = Update-ACMECertificate $s.alias
}
Get-ACMECertificate $s.alias -ExportPkcs12 $certPath
$cert = Import-PfxCertificate -FilePath $certPath -CertStoreLocation cert:\LocalMachine\My
if (Test-Path IIS:\SslBindings\$binding) {
Get-Item IIS:\SslBindings\$binding | Remove-Item
}
$cert | New-Item IIS:\SslBindings\$binding -SSLFlags $sniEnabled
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.