Advertisement
Guest User

script

a guest
Jul 18th, 2018
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.36 KB | None | 0 0
  1. Param(
  2. [bool]$Renew
  3. )
  4.  
  5. clear
  6. write-host ""
  7. write-host "----------------------------------------------------------------"
  8. write-host "
  9. _______ _ ___ _
  10. (_______) _ (_) / __|_) _
  11. _ _____ ____ _| |_ _ _| |__ _ ____ _____ _| |_ _____
  12. | | | ___ |/ ___|_ _) (_ __) |/ ___|____ (_ _) ___ |
  13. | |_____| ____| | | |_| | | | | ( (___/ ___ | | |_| ____|
  14. \______)_____)_| \__)_| |_| |_|\____)_____| \__)_____)
  15. _______ _
  16. (_______) (_) _ _
  17. _______ ___ ___ _ ___ _| |_ _____ ____ _| |_
  18. | ___ |/___)/___) |/___|_ _|____ | _ (_ _)
  19. | | | |___ |___ | |___ | | |_/ ___ | | | || |_
  20. |_| |_(___/(___/|_(___/ \__)_____|_| |_| \__)
  21. " -foregroundcolor cyan
  22. write-host ""
  23. write-host " Certificate Assistant v1.0"
  24. write-host " Automatic Let's Encrypt Certificates for Exchange 2016"
  25. write-host ""
  26. write-host " Frank Zoechling (www.FrankysWeb.de)"
  27. write-host " English translation by Sean Cox (www.QuillandGear.net)"
  28. write-host "----------------------------------------------------------------"
  29.  
  30. #Load ACME Sharp module
  31. write-host " Loading ACMESharp module..."
  32. Import-Module ACMESharp -ea 0
  33. $CheckACMEModule = get-module ACMESharp
  34. if (!$CheckACMEModule)
  35. {
  36. write-host " Warning: ACME Sharp Module not found" -foregroundcolor yellow
  37. write-host " Trying to install ACMESharp module..." -foregroundcolor yellow
  38. Install-Module -Name ACMESharp -AllowClobber
  39. Import-Module ACMESharp -ea 0
  40. $CheckACMEModule = get-module ACMESharp
  41. if (!$CheckACMEModule)
  42. {
  43. write-host " Error: ACME Sharp module could not be installed" -foregroundcolor red
  44. exit
  45. }
  46. }
  47.  
  48. #Load the IIS PowerShell module
  49. write-host " Loading IIS Web Administration Module..."
  50. Import-Module Webadministration -ea 0
  51. $CheckIISModule = get-module Webadministration
  52. if (!$CheckIISModule)
  53. {
  54. write-host " Web Administration Module not found" -foregroundcolor red
  55. exit
  56. }
  57.  
  58. #Load Exchange SnapIn
  59. write-host " Load Exchange Management Shell..."
  60. Add-PSSnapin *exchange* -ea 0
  61. $CheckExchangeSnapin = Get-PSSnapin *exchange*
  62. if (!$CheckExchangeSnapin)
  63. {
  64. write-host " Exchange SnapIn not found" -foregroundcolor red
  65. exit
  66. }
  67.  
  68. if ($renew -ne $True)
  69. {
  70. #Query the configured DNS names
  71. write-host ""
  72. write-host " Read Exchange configuration..."
  73. $ExchangeServer = (Get-ExchangeServer $env:computername).Name
  74. [array]$CertNames += ((Get-ClientAccessService -Identity $ExchangeServer).AutoDiscoverServiceInternalUri.Host).ToLower()
  75. [array]$CertNames += ((Get-OutlookAnywhere -Server $ExchangeServer).Internalhostname.Hostnamestring).ToLower()
  76. [array]$CertNames += ((Get-OutlookAnywhere -Server $ExchangeServer).ExternalHostname.Hostnamestring).ToLower()
  77. [array]$CertNames += ((Get-MapiVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
  78. [array]$CertNames += ((Get-MapiVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
  79. [array]$CertNames += ((Get-OabVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
  80. [array]$CertNames += ((Get-OabVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
  81. [array]$CertNames += ((Get-ActiveSyncVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
  82. [array]$CertNames += ((Get-ActiveSyncVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
  83. [array]$CertNames += ((Get-WebServicesVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
  84. [array]$CertNames += ((Get-WebServicesVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
  85. [array]$CertNames += ((Get-EcpVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
  86. [array]$CertNames += ((Get-EcpVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
  87. [array]$CertNames += ((Get-OwaVirtualDirectory -Server $ExchangeServer).Internalurl.Host).ToLower()
  88. [array]$CertNames += ((Get-OwaVirtualDirectory -Server $ExchangeServer).ExternalUrl.Host).ToLower()
  89. $CertNames = $CertNames | select –Unique
  90.  
  91. write-host "----------------------------------------------------------------"
  92. write-host ""
  93. write-host " The following DNS names were found:"
  94. write-host ""
  95. foreach ($Certname in $CertNames)
  96. {
  97. write-host " $certname" -foregroundcolor cyan
  98. }
  99. write-host ""
  100.  
  101. #Add additional names?
  102. $AddName = "y"
  103. while ($AddName -match "y")
  104. {
  105. $AddName = read-host " Do you want to add more DNS names to the certificate? (y/n)"
  106. if ($AddName -match "y")
  107. {
  108. $AddHost = read-host " Please enter DNS name"
  109. $CertNames += "$addhost"
  110. }
  111. }
  112.  
  113. #Output the DNS names
  114. write-host ""
  115. write-host " The following DNS names have been configured:"
  116. write-host ""
  117. foreach ($Certname in $CertNames)
  118. {
  119. write-host " $certname" -foregroundcolor cyan
  120. }
  121. write-host ""
  122.  
  123. #Email address for the ACME registration
  124. write-host " Which e-mail address should be used to register with Let's Encrypt?"
  125. write-host ""
  126. write-host " If a Let's Encrypt registry has already been performed on this computer,"
  127. write-host " no e-mail address must be specified."
  128. write-host
  129. $contact = read-host " E-Mail Address"
  130. $contactmail = "mailto:$contact"
  131. write-host
  132.  
  133. #Add task to refresh?
  134. write-host " Do you want to create a scheduled task to automatically"
  135. write-host " renew the certificate?"
  136. write-host ""
  137. $AutoRenewTask = read-host " Automatic renewal? (y/n)"
  138. if ($AutoRenewTask -match "y")
  139. {
  140. $username = read-host " Username for the task (domain \ user)"
  141. $SecurePassword = read-host " Password" -AsSecureString
  142. }
  143. write-host ""
  144.  
  145. #----------------------------------------------
  146.  
  147. #Create task to renew
  148. if ($AutoRenewTask -match "y")
  149. {
  150. $installpath = (get-location).Path
  151.  
  152. #Create a scheduled task
  153. $time = "23:00"
  154. $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
  155. $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
  156. $startTime = "$time" | get-date -format s
  157.  
  158. $taskService = New-Object -ComObject Schedule.Service
  159. $taskService.Connect()
  160.  
  161. $rootFolder = $taskService.GetFolder($NULL)
  162.  
  163. $taskDefinition = $taskService.NewTask(0)
  164.  
  165. $registrationInformation = $taskDefinition.RegistrationInfo
  166.  
  167. $registrationInformation = $taskDefinition.RegistrationInfo
  168. $registrationInformation.Description = "Let's Encrypt certificate renewal - www.FrankysWeb.de"
  169. $registrationInformation.Author = $username
  170.  
  171. $taskPrincipal = $taskDefinition.Principal
  172. $taskPrincipal.LogonType = 1
  173. $taskPrincipal.UserID = $username
  174. $taskPrincipal.RunLevel = 0
  175.  
  176. $taskSettings = $taskDefinition.Settings
  177. $taskSettings.StartWhenAvailable = $true
  178. $taskSettings.RunOnlyIfNetworkAvailable = $true
  179. $taskSettings.Priority = 7
  180.  
  181. $taskTriggers = $taskDefinition.Triggers
  182.  
  183. $executionTrigger = $taskTriggers.Create(2)
  184. $executionTrigger.StartBoundary = $startTime
  185.  
  186. $taskAction = $taskDefinition.Actions.Create(0)
  187. $taskAction.Path = "powershell.exe"
  188. $taskAction.Arguments = "-Command `"&'$installpath\CertificateAssistant.ps1' -renew:`$true`""
  189.  
  190. $job = $rootFolder.RegisterTaskDefinition("Lets Encrypt certificate renewal (www.FrankysWeb.de)" , $taskDefinition, 6, $username, $password, 1)
  191. }
  192.  
  193. #----------------------------------------------
  194. clear
  195. write-host ""
  196. write-host "---------------------------------------------------------------------------" -foregroundcolor green
  197. write-host " All information is available, should the certificate be configured? " -foregroundcolor green
  198. write-host "---------------------------------------------------------------------------" -foregroundcolor green
  199. write-host ""
  200. read-host "Start configuration? (Enter for Next / CTRL + C to cancel)"
  201. write-host ""
  202. #Perform DNS tests
  203. write-host "Check DNS records..."
  204. write-host ""
  205. $error = 0
  206. foreach ($CertName in $CertNames)
  207. {
  208. $DNSIP = (Resolve-DnsName $CertName -Server 8.8.8.8 -DnsOnly -ea 0).IPAddress
  209. $ExtIP = (Invoke-RestMethod http://ipinfo.io/json).IP
  210. if ($DNSIP -ne $ExtIP)
  211. {
  212. write-host "Error: $CertName could not be resolved to IP $ExtIP" -foregroundcolor red
  213. $error++
  214. }
  215. else
  216. {
  217. write-host "DNS test passed: $CertName was resolved in IP $ExtIP" -foregroundcolor green
  218. }
  219. }
  220. if ($error -gt 0)
  221. {
  222. write-host ""
  223. write-host "Error: Let's Encrypt must be able to validate the DNS names. This Exchange Server" -foregroundcolor red
  224. write-host " must be accessible via port 80 (http) under the configured DNS names from" -foregroundcolor red
  225. write-host " the Internet. For this test it tried to determine the WAN IP and resolve" -foregroundcolor red
  226. write-host " it via Google DNS" -foregroundcolor red
  227. write-host ""
  228. exit
  229. }
  230.  
  231. #Check if Vault exists
  232. write-host "Check if a vault already exists..."
  233. $Vault = Get-ACMEVault
  234. if (!$Vault)
  235. {
  236. write-host "No Vault found, try to create a new Vault..."
  237. $CreateVault = Initialize-ACMEVault
  238. sleep 1
  239. $Vault = Get-ACMEVault
  240. if (!$Vault)
  241. {
  242. write-host "Error: Vault could not be created" -foregroundcolor red
  243. exit
  244. }
  245. }
  246.  
  247. #Check if Let's Encrypt registry is present
  248. write-host "Check Let's Encrypt Registration..."
  249. $Registration = Get-ACMERegistration
  250. if (!$Registration)
  251. {
  252. write-host "Warning: No registration was found at Let's Encrypt, new registration is being performed" -foregroundcolor yellow
  253. $Registration = New-ACMERegistration -Contacts $contactmail -AcceptTos
  254. if (!$Registration)
  255. {
  256. write-host "Error: Could not register with Let's Encrypt" -foregroundcolor red
  257. exit
  258. }
  259. else
  260. {
  261. write-host "Registration at Let's Encrypt was done" -foregroundcolor green
  262. }
  263. }
  264.  
  265. #Prepare domain names validation
  266. $CertSubject = ((Get-OutlookAnywhere -Server $ExchangeServer).ExternalHostname.Hostnamestring).ToLower()
  267. $ExchangeSANID = 1
  268. foreach ($ExchangeSAN in $CertNames)
  269. {
  270. $CurrentDate = get-date -format ddMMyyyy
  271. $ACMEAlias = "Cert" + "$CurrentDate" + "-" + "$ExchangeSANID"
  272. $ExchangeSANID++
  273.  
  274. write-host "New Identifier:"
  275. write-host " DNS: $ExchangeSAN"
  276. write-host " Alias: $ACMEAlias"
  277. $NewID = New-ACMEIdentifier -Dns $ExchangeSAN -Alias $ACMEAlias
  278. write-host "Prepare validation:"
  279. write-host " Alias $ACMEAlias"
  280. $ValidateReq = Complete-ACMEChallenge $ACMEAlias -ChallengeType http-01 -Handler iis -HandlerParameters @{ WebSiteRef = 'Default Web Site' }
  281. [Array]$ACMEAliasArray += $ACMEAlias
  282. if ($ExchangeSAN -eq $CertSubject) {$SubjectAlias = $ACMEAlias}
  283. }
  284.  
  285. #Change Let's Encrypt IIS directory to HTTP
  286. write-host "Change Let's Encrypt IIS directory to HTTP..."
  287. $IISDir = Set-WebConfigurationProperty -Location "Default Web Site/.well-known" -Filter 'system.webserver/security/access' -name "sslFlags" -Value None
  288. $IISDirCeck = (Get-WebConfigurationProperty -Location "Default Web Site/.well-known" -Filter 'system.webserver/security/access' -name "sslFlags").Value
  289. if ($IISDirCeck -match 0)
  290. {
  291. write-host "Changed to HTTP successfully" -foregroundcolor green
  292. }
  293. else
  294. {
  295. write-host "Error: Change to HTTP was unsuccessful" -foregroundcolor red
  296. exit
  297. }
  298.  
  299. #Validate domain names
  300. write-host "DNS names can be validated by Let's Encrypt..."
  301. foreach ($ACMEAlias in $ACMEAliasArray)
  302. {
  303. write-host "Running validation: $ACMEAlias"
  304. $Validate = Submit-ACMEChallenge $ACMEAlias -ChallengeType http-01
  305. }
  306.  
  307. write-host "30 Second wait..."
  308. sleep -seconds 30
  309.  
  310. #Check the validation
  311. write-host "Check whether the DNS names have been validated..."
  312. foreach ($ACMEAlias in $ACMEAliasArray)
  313. {
  314. write-host "Update Alias: $ACMEAlias"
  315. $ACMEIDUpdate = Update-ACMEIdentifier $ACMEAlias
  316. $ACMEIDStatus = $ACMEIDUpdate.Status
  317. if ($ACMEIDStatus -match "valid")
  318. {
  319. write-host "Validation OK" -foregroundcolor green
  320. }
  321. else
  322. {
  323. write-host "Error: Validation for alias $ACMEAlias failed" -foregroundcolor red
  324. exit
  325. }
  326. }
  327.  
  328. #Prepare and submit the certificate
  329. $SANAlias = "SAN" + "$CurrentDate"
  330. $NewCert = New-ACMECertificate $SubjectAlias -Generate -AlternativeIdentifierRefs $ACMEAliasArray -Alias $SANAlias
  331. $SubmitNewCert = Submit-ACMECertificate $SANAlias
  332.  
  333. #Wait until the certificate has been issued
  334. write-host "30 Second wait..."
  335. sleep -seconds 30
  336.  
  337. #Check status
  338. write-host "Check the certificate..."
  339. $UpdateNewCert = Update-ACMECertificate $SANAlias
  340. $CertStatus = (Get-ACMECertificate $SANAlias).CertificateRequest.Statuscode
  341. sleep 5
  342. if ($CertStatus -match "OK")
  343. {
  344. write-host "Certificate OK" -foregroundcolor green
  345. }
  346. else
  347. {
  348. write-host "Error: Certificate not issued" -foregroundcolor red
  349. exit
  350. }
  351.  
  352. #Export the certificate from Vault and assign to Exchange
  353. write-host "Export the certificate to $env:temp"
  354. $CertPath = "$env:temp" + "\" + "$SANAlias" + ".pfx"
  355. $PFXPasswort = Get-Random -Minimum 1000000 -Maximum 9999999
  356. $CertExport = Get-ACMECertificate $SANAlias -ExportPkcs12 $CertPath -CertificatePassword $PFXPasswort
  357. write-host "Check whether the certificate has been exported..."
  358. if (test-path $CertPath)
  359. {
  360. write-host "Certificate has been successfully exported" -foregroundcolor green
  361. }
  362. else
  363. {
  364. write-host "Error: The certificate was not exported" -foregroundcolor red
  365. exit
  366. }
  367.  
  368. write-host "Assign and activate in Exchange"
  369. $ImportPassword = ConvertTo-SecureString -String $PFXPasswort -Force –AsPlainText
  370. Import-ExchangeCertificate -FileName $CertPath -FriendlyName $ExchangeSubject -Password $ImportPassword -PrivateKeyExportable:$true | Enable-ExchangeCertificate -Services "SMTP, IMAP, POP, IIS" –force
  371.  
  372. write-host "Check whether the certificate has been activated"
  373. $CurrentCertThumbprint = (Get-ChildItem -Path IIS:SSLBindings | where {$_.port -match "443" -and $_.IPAddress -match "0.0.0.0" } | select Thumbprint).Thumbprint
  374. $ExportThumbprint = $CertExport.Thumbprint
  375. if ($CurrentCertThumbprint -eq $ExportThumbprint)
  376. {
  377. write-host "The certificate has been successfully activated" -foregroundcolor green
  378. }
  379. else
  380. {
  381. write-host "Activation failed" -foregroundcolor red
  382. exit
  383. }
  384. }
  385.  
  386. #---------------------------------------RENEW------------------------------------------------
  387. #Automatic renewal
  388. if ($renew -eq $True)
  389. {
  390. $PFXPasswort = Get-Random -Minimum 1000000 -Maximum 9999999
  391.  
  392. $CurrentCertThumbprint = (Get-ChildItem -Path IIS:SSLBindings | where {$_.port -match "443" -and $_.IPAddress -match "0.0.0.0" } | select Thumbprint).Thumbprint
  393. $ExchangeCertificate = Get-ExchangeCertificate -Thumbprint $CurrentCertThumbprint
  394. $ExchangeSANs = ($ExchangeCertificate.CertificateDomains).Address
  395. $ExchangeSubject = $ExchangeCertificate.Subject.Replace("CN=","")
  396.  
  397. if ($ExchangeSANs -notcontains $ExchangeSubject) {$ExchangeSANs += $ExchangeSubject}
  398.  
  399. $CurrentDate = get-date
  400. $VaildTill = $ExchangeCertificate.NotAfter
  401. $DaysLeft = ($VaildTill - $CurrentDate).Days
  402. if ($DaysLeft -le 4) #4 days before expiration
  403. {
  404. $ExchangeSANID = 1
  405. foreach ($ExchangeSAN in $ExchangeSANs)
  406. {
  407. $CurrentDate = get-date -format ddMMyyyy
  408. $ACMEAlias = "Cert" + "$CurrentDate" + "-" + "$ExchangeSANID"
  409. $ExchangeSANID++
  410. New-ACMEIdentifier -Dns $ExchangeSAN -Alias $ACMEAlias
  411. Complete-ACMEChallenge $ACMEAlias -ChallengeType http-01 -Handler iis -HandlerParameters @{ WebSiteRef = 'Default Web Site' }
  412. [Array]$ACMEAliasArray += $ACMEAlias
  413. if ($ExchangeSAN -match $ExchangeSubject) {$ExchangeSubjectAlias = $ACMEAlias}
  414. }
  415.  
  416. foreach ($ACMEAlias in $ACMEAliasArray)
  417. {
  418. Submit-ACMEChallenge $ACMEAlias -ChallengeType http-01
  419. }
  420.  
  421. sleep -seconds 30
  422.  
  423. foreach ($ACMEAlias in $ACMEAliasArray)
  424. {
  425. Update-ACMEIdentifier $ACMEAlias
  426. }
  427.  
  428. $SANAlias = "SAN" + "$CurrentDate"
  429. New-ACMECertificate $ExchangeSubjectAlias -Generate -AlternativeIdentifierRefs $ACMEAliasArray -Alias $SANAlias
  430. Submit-ACMECertificate $SANAlias
  431.  
  432. sleep -seconds 30
  433.  
  434. Update-ACMECertificate $SANAlias
  435.  
  436. $CertPath = "$env:temp" + "\" + "$SANAlias" + ".pfx"
  437. $CertExport = Get-ACMECertificate $SANAlias -ExportPkcs12 $CertPath -CertificatePassword $PFXPasswort
  438.  
  439. $ImportPassword = ConvertTo-SecureString -String $PFXPasswort -Force –AsPlainText
  440. Import-ExchangeCertificate -FileName $CertPath -FriendlyName $ExchangeSubject -Password $ImportPassword -PrivateKeyExportable:$true | Enable-ExchangeCertificate -Services "SMTP, IMAP, POP, IIS" –force
  441. }
  442. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement