Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Param(
- [bool]$Renew
- )
- clear
- write-host ""
- write-host "----------------------------------------------------------------"
- write-host "
- _______ _ ___ _
- (_______) _ (_) / __|_) _
- _ _____ ____ _| |_ _ _| |__ _ ____ _____ _| |_ _____
- | | | ___ |/ ___|_ _) (_ __) |/ ___|____ (_ _) ___ |
- | |_____| ____| | | |_| | | | | ( (___/ ___ | | |_| ____|
- \______)_____)_| \__)_| |_| |_|\____)_____| \__)_____)
- _______ _
- (_______) (_) _ _
- _______ ___ ___ _ ___ _| |_ _____ ____ _| |_
- | ___ |/___)/___) |/___|_ _|____ | _ (_ _)
- | | | |___ |___ | |___ | | |_/ ___ | | | || |_
- |_| |_(___/(___/|_(___/ \__)_____|_| |_| \__)
- " -foregroundcolor cyan
- write-host ""
- write-host " Certificate Assistant v1.0"
- write-host " Automatic Let's Encrypt Certificates for Exchange 2016"
- write-host ""
- write-host " Frank Zoechling (www.FrankysWeb.de)"
- write-host " English translation by Sean Cox (www.QuillandGear.net)"
- write-host "----------------------------------------------------------------"
- #Load ACME Sharp module
- write-host " Loading ACMESharp module..."
- Import-Module ACMESharp -ea 0
- $CheckACMEModule = get-module ACMESharp
- if (!$CheckACMEModule)
- {
- write-host " Warning: ACME Sharp Module not found" -foregroundcolor yellow
- write-host " Trying to install ACMESharp module..." -foregroundcolor yellow
- Install-Module -Name ACMESharp -AllowClobber
- Import-Module ACMESharp -ea 0
- $CheckACMEModule = get-module ACMESharp
- if (!$CheckACMEModule)
- {
- write-host " Error: ACME Sharp module could not be installed" -foregroundcolor red
- exit
- }
- }
- #Load the IIS PowerShell module
- write-host " Loading IIS Web Administration Module..."
- Import-Module Webadministration -ea 0
- $CheckIISModule = get-module Webadministration
- if (!$CheckIISModule)
- {
- write-host " Web Administration Module not found" -foregroundcolor red
- exit
- }
- #Load Exchange SnapIn
- write-host " Load Exchange Management Shell..."
- Add-PSSnapin *exchange* -ea 0
- $CheckExchangeSnapin = Get-PSSnapin *exchange*
- if (!$CheckExchangeSnapin)
- {
- write-host " Exchange SnapIn not found" -foregroundcolor red
- exit
- }
- if ($renew -ne $True)
- {
- #Query the configured DNS names
- write-host ""
- write-host " Read Exchange configuration..."
- $ExchangeServer = (Get-ExchangeServer $env:computername).Name
- [array]$CertNames += ((Get-ClientAccessService -Identity $ExchangeServer).AutoDiscoverServiceInternalUri.Host).ToLower()
- [array]$CertNames += ((Get-OutlookAnywhere -Server $ExchangeServer).Internalhostname.Hostnamestring).ToLower()
- [array]$CertNames += ((Get-OutlookAnywhere -Server $ExchangeServer).ExternalHostname.Hostnamestring).ToLower()
- [array]$CertNames += ((Get-MapiVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
- [array]$CertNames += ((Get-MapiVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
- [array]$CertNames += ((Get-OabVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
- [array]$CertNames += ((Get-OabVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
- [array]$CertNames += ((Get-ActiveSyncVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
- [array]$CertNames += ((Get-ActiveSyncVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
- [array]$CertNames += ((Get-WebServicesVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
- [array]$CertNames += ((Get-WebServicesVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
- [array]$CertNames += ((Get-EcpVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
- [array]$CertNames += ((Get-EcpVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
- [array]$CertNames += ((Get-OwaVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
- [array]$CertNames += ((Get-OwaVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
- $CertNames = $CertNames | select –Unique
- write-host "----------------------------------------------------------------"
- write-host ""
- write-host " The following DNS names were found:"
- write-host ""
- foreach ($Certname in $CertNames)
- {
- write-host " $certname" -foregroundcolor cyan
- }
- write-host ""
- #Add additional names?
- $AddName = "y"
- while ($AddName -match "y")
- {
- $AddName = read-host " Do you want to add more DNS names to the certificate? (y/n)"
- if ($AddName -match "y")
- {
- $AddHost = read-host " Please enter DNS name"
- $CertNames += "$addhost"
- }
- }
- #Output the DNS names
- write-host ""
- write-host " The following DNS names have been configured:"
- write-host ""
- foreach ($Certname in $CertNames)
- {
- write-host " $certname" -foregroundcolor cyan
- }
- write-host ""
- #Email address for the ACME registration
- write-host " Which e-mail address should be used to register with Let's Encrypt?"
- write-host ""
- write-host " If a Let's Encrypt registry has already been performed on this computer,"
- write-host " no e-mail address must be specified."
- write-host
- $contact = read-host " E-Mail Address"
- $contactmail = "mailto:$contact"
- write-host
- #Add task to refresh?
- write-host " Do you want to create a scheduled task to automatically"
- write-host " renew the certificate?"
- write-host ""
- $AutoRenewTask = read-host " Automatic renewal? (y/n)"
- if ($AutoRenewTask -match "y")
- {
- $username = read-host " Username for the task (domain \ user)"
- $SecurePassword = read-host " Password" -AsSecureString
- }
- write-host ""
- #----------------------------------------------
- #Create task to renew
- if ($AutoRenewTask -match "y")
- {
- $installpath = (get-location).Path
- #Create a scheduled task
- $time = "23:00"
- $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
- $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
- $startTime = "$time" | get-date -format s
- $taskService = New-Object -ComObject Schedule.Service
- $taskService.Connect()
- $rootFolder = $taskService.GetFolder($NULL)
- $taskDefinition = $taskService.NewTask(0)
- $registrationInformation = $taskDefinition.RegistrationInfo
- $registrationInformation = $taskDefinition.RegistrationInfo
- $registrationInformation.Description = "Let's Encrypt certificate renewal - www.FrankysWeb.de"
- $registrationInformation.Author = $username
- $taskPrincipal = $taskDefinition.Principal
- $taskPrincipal.LogonType = 1
- $taskPrincipal.UserID = $username
- $taskPrincipal.RunLevel = 0
- $taskSettings = $taskDefinition.Settings
- $taskSettings.StartWhenAvailable = $true
- $taskSettings.RunOnlyIfNetworkAvailable = $true
- $taskSettings.Priority = 7
- $taskTriggers = $taskDefinition.Triggers
- $executionTrigger = $taskTriggers.Create(2)
- $executionTrigger.StartBoundary = $startTime
- $taskAction = $taskDefinition.Actions.Create(0)
- $taskAction.Path = "powershell.exe"
- $taskAction.Arguments = "-Command `"&'$installpath\CertificateAssistant.ps1' -renew:`$true`""
- $job = $rootFolder.RegisterTaskDefinition("Lets Encrypt certificate renewal (www.FrankysWeb.de)" , $taskDefinition, 6, $username, $password, 1)
- }
- #----------------------------------------------
- clear
- write-host ""
- write-host "---------------------------------------------------------------------------" -foregroundcolor green
- write-host " All information is available, should the certificate be configured? " -foregroundcolor green
- write-host "---------------------------------------------------------------------------" -foregroundcolor green
- write-host ""
- read-host "Start configuration? (Enter for Next / CTRL + C to cancel)"
- write-host ""
- #Perform DNS tests
- write-host "Check DNS records..."
- write-host ""
- $error = 0
- foreach ($CertName in $CertNames)
- {
- $DNSIP = (Resolve-DnsName $CertName -Server 8.8.8.8 -DnsOnly -ea 0).IPAddress
- $ExtIP = (Invoke-RestMethod http://ipinfo.io/json).IP
- if ($DNSIP -ne $ExtIP)
- {
- write-host "Error: $CertName could not be resolved to IP $ExtIP" -foregroundcolor red
- $error++
- }
- else
- {
- write-host "DNS test passed: $CertName was resolved in IP $ExtIP" -foregroundcolor green
- }
- }
- if ($error -gt 0)
- {
- write-host ""
- write-host "Error: Let's Encrypt must be able to validate the DNS names. This Exchange Server" -foregroundcolor red
- write-host " must be accessible via port 80 (http) under the configured DNS names from" -foregroundcolor red
- write-host " the Internet. For this test it tried to determine the WAN IP and resolve" -foregroundcolor red
- write-host " it via Google DNS" -foregroundcolor red
- write-host ""
- exit
- }
- #Check if Vault exists
- write-host "Check if a vault already exists..."
- $Vault = Get-ACMEVault
- if (!$Vault)
- {
- write-host "No Vault found, try to create a new Vault..."
- $CreateVault = Initialize-ACMEVault
- sleep 1
- $Vault = Get-ACMEVault
- if (!$Vault)
- {
- write-host "Error: Vault could not be created" -foregroundcolor red
- exit
- }
- }
- #Check if Let's Encrypt registry is present
- write-host "Check Let's Encrypt Registration..."
- $Registration = Get-ACMERegistration
- if (!$Registration)
- {
- write-host "Warning: No registration was found at Let's Encrypt, new registration is being performed" -foregroundcolor yellow
- $Registration = New-ACMERegistration -Contacts $contactmail -AcceptTos
- if (!$Registration)
- {
- write-host "Error: Could not register with Let's Encrypt" -foregroundcolor red
- exit
- }
- else
- {
- write-host "Registration at Let's Encrypt was done" -foregroundcolor green
- }
- }
- #Prepare domain names validation
- $CertSubject = ((Get-OutlookAnywhere -Server $ExchangeServer).ExternalHostname.Hostnamestring).ToLower()
- $ExchangeSANID = 1
- foreach ($ExchangeSAN in $CertNames)
- {
- $CurrentDate = get-date -format ddMMyyyy
- $ACMEAlias = "Cert" + "$CurrentDate" + "-" + "$ExchangeSANID"
- $ExchangeSANID++
- write-host "New Identifier:"
- write-host " DNS: $ExchangeSAN"
- write-host " Alias: $ACMEAlias"
- $NewID = New-ACMEIdentifier -Dns $ExchangeSAN -Alias $ACMEAlias
- write-host "Prepare validation:"
- write-host " Alias $ACMEAlias"
- $ValidateReq = Complete-ACMEChallenge $ACMEAlias -ChallengeType http-01 -Handler iis -HandlerParameters @{ WebSiteRef = 'Default Web Site' }
- [Array]$ACMEAliasArray += $ACMEAlias
- if ($ExchangeSAN -eq $CertSubject) {$SubjectAlias = $ACMEAlias}
- }
- #Change Let's Encrypt IIS directory to HTTP
- write-host "Change Let's Encrypt IIS directory to HTTP..."
- $IISDir = Set-WebConfigurationProperty -Location "Default Web Site/.well-known" -Filter 'system.webserver/security/access' -name "sslFlags" -Value None
- $IISDirCeck = (Get-WebConfigurationProperty -Location "Default Web Site/.well-known" -Filter 'system.webserver/security/access' -name "sslFlags").Value
- if ($IISDirCeck -match 0)
- {
- write-host "Changed to HTTP successfully" -foregroundcolor green
- }
- else
- {
- write-host "Error: Change to HTTP was unsuccessful" -foregroundcolor red
- exit
- }
- #Validate domain names
- write-host "DNS names can be validated by Let's Encrypt..."
- foreach ($ACMEAlias in $ACMEAliasArray)
- {
- write-host "Running validation: $ACMEAlias"
- $Validate = Submit-ACMEChallenge $ACMEAlias -ChallengeType http-01
- }
- write-host "30 Second wait..."
- sleep -seconds 30
- #Check the validation
- write-host "Check whether the DNS names have been validated..."
- foreach ($ACMEAlias in $ACMEAliasArray)
- {
- write-host "Update Alias: $ACMEAlias"
- $ACMEIDUpdate = Update-ACMEIdentifier $ACMEAlias
- $ACMEIDStatus = $ACMEIDUpdate.Status
- if ($ACMEIDStatus -match "valid")
- {
- write-host "Validation OK" -foregroundcolor green
- }
- else
- {
- write-host "Error: Validation for alias $ACMEAlias failed" -foregroundcolor red
- exit
- }
- }
- #Prepare and submit the certificate
- $SANAlias = "SAN" + "$CurrentDate"
- $NewCert = New-ACMECertificate $SubjectAlias -Generate -AlternativeIdentifierRefs $ACMEAliasArray -Alias $SANAlias
- $SubmitNewCert = Submit-ACMECertificate $SANAlias
- #Wait until the certificate has been issued
- write-host "30 Second wait..."
- sleep -seconds 30
- #Check status
- write-host "Check the certificate..."
- $UpdateNewCert = Update-ACMECertificate $SANAlias
- $CertStatus = (Get-ACMECertificate $SANAlias).CertificateRequest.Statuscode
- sleep 5
- if ($CertStatus -match "OK")
- {
- write-host "Certificate OK" -foregroundcolor green
- }
- else
- {
- write-host "Error: Certificate not issued" -foregroundcolor red
- exit
- }
- #Export the certificate from Vault and assign to Exchange
- write-host "Export the certificate to $env:temp"
- $CertPath = "$env:temp" + "\" + "$SANAlias" + ".pfx"
- $PFXPasswort = Get-Random -Minimum 1000000 -Maximum 9999999
- $CertExport = Get-ACMECertificate $SANAlias -ExportPkcs12 $CertPath -CertificatePassword $PFXPasswort
- write-host "Check whether the certificate has been exported..."
- if (test-path $CertPath)
- {
- write-host "Certificate has been successfully exported" -foregroundcolor green
- }
- else
- {
- write-host "Error: The certificate was not exported" -foregroundcolor red
- exit
- }
- write-host "Assign and activate in Exchange"
- $ImportPassword = ConvertTo-SecureString -String $PFXPasswort -Force –AsPlainText
- Import-ExchangeCertificate -FileName $CertPath -FriendlyName $ExchangeSubject -Password $ImportPassword -PrivateKeyExportable:$true | Enable-ExchangeCertificate -Services "SMTP, IMAP, POP, IIS" –force
- write-host "Check whether the certificate has been activated"
- $CurrentCertThumbprint = (Get-ChildItem -Path IIS:SSLBindings | where {$_.port -match "443" -and $_.IPAddress -match "0.0.0.0" } | select Thumbprint).Thumbprint
- $ExportThumbprint = $CertExport.Thumbprint
- if ($CurrentCertThumbprint -eq $ExportThumbprint)
- {
- write-host "The certificate has been successfully activated" -foregroundcolor green
- }
- else
- {
- write-host "Activation failed" -foregroundcolor red
- exit
- }
- }
- #---------------------------------------RENEW------------------------------------------------
- #Automatic renewal
- if ($renew -eq $True)
- {
- $PFXPasswort = 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}
- $CurrentDate = get-date
- $VaildTill = $ExchangeCertificate.NotAfter
- $DaysLeft = ($VaildTill - $CurrentDate).Days
- if ($DaysLeft -le 4) #4 days before expiration
- {
- $ExchangeSANID = 1
- foreach ($ExchangeSAN in $ExchangeSANs)
- {
- $CurrentDate = get-date -format ddMMyyyy
- $ACMEAlias = "Cert" + "$CurrentDate" + "-" + "$ExchangeSANID"
- $ExchangeSANID++
- New-ACMEIdentifier -Dns $ExchangeSAN -Alias $ACMEAlias
- 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)
- {
- Submit-ACMEChallenge $ACMEAlias -ChallengeType http-01
- }
- sleep -seconds 30
- foreach ($ACMEAlias in $ACMEAliasArray)
- {
- 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"
- $CertExport = Get-ACMECertificate $SANAlias -ExportPkcs12 $CertPath -CertificatePassword $PFXPasswort
- $ImportPassword = ConvertTo-SecureString -String $PFXPasswort -Force –AsPlainText
- Import-ExchangeCertificate -FileName $CertPath -FriendlyName $ExchangeSubject -Password $ImportPassword -PrivateKeyExportable:$true | Enable-ExchangeCertificate -Services "SMTP, IMAP, POP, IIS" –force
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement