Windows Servers: Import SSL certificate on IIS and set up HTTPS binding using PowerShell
In this blog I will share one way to import SSL certificate on IIS and set up HTTPS binding to use the imported SSL certificate using PowerShell.
If you already imported the new SSL certificate, you can skip that step and continue with the binding step.
My blogs have relatively simple, and sometimes complex, examples and I’m hoping that you will be able to tailor them to your need or use them in your own scripts.
Prerequisites
- Windows IIS Server.
- Log on to the server with an Administrator account.
Introduction
The goal of this blog is to show one way to accomplish a task. It is not to show how to write a perfect script, the perfect solution to a challenge or the perfect process to accomplish a task.
I was asked to replace the soon to be expired SSL certificate on couple IIS servers and set up HTTPS binding to use the new SSL certificate. PowerShell scripting should make this task an easy task to accomplish.
PowerShell Cmdlets
- Import-Module Adds modules to the current session.
- WebAdministration This reference provides cmdlet descriptions and syntax for all Web Administration cmdlets. It lists the cmdlets in alphabetical order based on the verb at the beginning of the cmdlet.
- New-Object Creates an instance of a Microsoft .NET Framework or COM object.
- Get-ChildItem Gets the items and child items in one or more specified locations.
- Get-WebBinding Gets the bindings on an IIS site.
Manual steps to complete the task
To accomplish this task manually, the following steps need to be completed:
- Import PFX certificate into IIS.
- For each website, setup binding to use the new SSL certificate over HTTPS.
Script steps to complete the task
PowerShell script needs to do steps similar to the manual steps .
- Import PFX certificate into IIS. Skip this step if the new certificate is already imported into IIS.
- Save the certificate thumbprint if you just imported the new certificate into IIS or get the certificate thumbprint if the new certificate is already imported into IIS.
- For every HTTS binding, if the binding certificate expiration date is less than new certificate expiration date, bind the HTTPS to the new certificate.
Import WebAdministration Module
We need to import the WebAdministration module to interact with IIS.
1 |
Import-Module -Name WebAdministration |
Import SSL certificate on IIS & save the certificate thumbprint object
- Save pxf file path in a variable.
- Save pfx file password in a variable.
- Initializes a new instance of the X509Certificates class.
- Import certificate to the new X509Certificates class.
- Initializes a new instance of the X509Store class using WebHosting for StoreName and LocalMachine for StoreLocation.
- Open X509Store instance as ReadWrite.
- Add pfx certificate to the store.
- Close X509Store instance.
- Save the certificate thumbprint object, in $CertThumbprint, for a later use.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 1. pxf file path $certPath = "C:\TEMP\Cert\2022-Cert.pfx" # 2. pfx file password $certPass = "password123" # 3. Initializes a new instance of the X509Certificates class $pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 # 4. Import certificate to the new X509Certificates class $pfx.Import($certPath, $certPass, "Exportable,PersistKeySet") # 5. Initializes a new instance of the X509Store $CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("WebHosting","LocalMachine") # 6. Open X509Store instance as ReadWrite $CertStore.Open("ReadWrite") # 7. Add pfx certificate to the store $CertStore.Add($pfx) # 8. Close X509Store instance $CertStore.Close() # 9. Save the certificate thumbprint $CertThumbprint = $pfx |
Get existing certificates in the My (Personal) and WebHosting stores
We need to get all imported/installed certificates from My (Personal) and WebHosting stores. This will be used to get more information about exiting binding.
1 2 3 |
# Get existing certificates in the My (Personal) and WebHosting stores # This will be used to get more information about exiting binding $Certificates = (Get-ChildItem -Path CERT:LocalMachine/My) + (Get-ChildItem -Path CERT:LocalMachine/WebHosting) |
Get the certificate thumbprint
Use Get-ChildItem to get imported certificate thumbprint from the local machine My (Personal) or WebHosting store. Save the first certificate thumbprint in the list.
1 2 3 |
# If the new certificate is already imported to "WebHosting" $Thumbprints = Get-ChildItem -path cert:\LocalMachine\WebHosting $CertThumbprint = $Thumbprints[0] |
Or, If you know the value of the new certificate thumbprint, search for it in all existing certificates in My (Personal) and WebHosting certificate stores on the local machine.
1 2 3 |
# If you know the certification thumbprint, search for the new certificate thumbprint $NewCertThumbprint = "775D97416CE89C6DCFD4D8DE99A980861EEB8092" $CertThumbprint = $Certificates | Where {$_.Thumbprint -eq $NewCertThumbprint} |
Bind HTTPS to use SSL certificate
- Get existing SSL bindings in IIS, $Bindings.
- Repeat the following steps for each SSL binding, $Binding .
- If the existing SSL binding has sites, $Binding.Sites, continue. Otherwise check the next existing SSL binding.
- Get the SSL binding certificate object, $BindCert.
- If the certificate object expiration date, $BindCert.NotAfter, is less than the new certificate expiration date, $CertThumbprint.NotAfter, continue. Otherwise, display an information message.
- $Binding.Sites contains either one site, string value, or multiple sites, array.
- If $Binding.Sites contains one site, convert the string value to an array, $Sites.
- For each site in $Sites, bind the site to the new SSL certificate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# 1. Get existing SSL bindings in IIS $Bindings = Get-ChildItem -Path IIS:SSLBindings ForEach ($Binding in $Bindings) { # 3. If the existing SSL binding has sites, continue If ($Binding.Sites) { # 4. Get the SSL binding certificate object $BindCert = $Certificates | Where-Object -Property Thumbprint -EQ -Value $Binding.Thumbprint If ($BindCert.NotAfter -lt $CertThumbprint.NotAfter) { # Display Site and bind information to be updated [PsCustomObject]@{ Sites = $Binding.Sites.Value Thumbprint = $Binding.Thumbprint CertificateFriendlyName = $BindCert.FriendlyName CertificateDnsNameList = $BindCert.DnsNameList CertificateNotAfter = $BindCert.NotAfter CertificateIssuer = $BindCert.Issuer } # 7. Convert string value to an array, if only one site exists. $Sites = If ($Binding.Sites.Value.GetType().Name -eq "String") { @($Binding.Sites.Value) } Else { $Binding.Sites.Value } # 8. For each site in $Sites, bind the site to the new SSL certificate ForEach ($Site in $Sites) { Write-Host "*** Will bind [$Site] to the new certificate" (Get-WebBinding -Name $Site -Port 443 -Protocol "https").AddSslCertificate($thumbprints[0].Thumbprint, "WebHosting") } } Else { Write-Host "--- New binding for [$($Binding.Sites.Value)] is not required" } } } |
Conclusion
In this blog we explored how to import SSL certificate on IIS and set up HTTPS binding to use the imported SSL certificate using PowerShell.
I hope this blog helps you work smarter, faster and more efficient. Good luck.
Did you find this blog easy to follow and helpful to you? Let me know in the comments below.
Disclaimer
Purpose of the code contained in blog is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Disclaimer
Purpose of the code contained in blog is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Hi tried this, there are number of syntax errors, could you take a second look at this please? Specifically your value for the vairable $#91? Not valid.
Thank you so much for pointing out this issue. Code has been fixed.