I have 3 websites: aaa.my-domain.com
, bbb.my-domain.com
and ccc.my-domain.com
all using a single wildcard certificate *.my-domain.com
on IIS 7.5 Windows Server 2008R2 64-bit. That certificate expires in a month and I have a new wildcard certificate *.my-domain.com
on my server ready.
I want all those domains to use the new wildcard certificate without noticeable downtime.
I tried the usual through the UI starting with replacing the certificate for aaa.my-domain.com:
But when I press OK, I get the following error:
--------------------------- Edit Site Binding ---------------------------
At least one other site is using the same HTTPS binding and the binding is configured with a different certificate. Are you sure that you want to reuse this HTTPS binding and reassign the other site or sites to use the new certificate?
--------------------------- Yes No ---------------------------
When I click Yes, I get the following message:
--------------------------- Edit Site Binding ---------------------------
The certificate associated with this binding is also assigned to another site's binding. Editing this binding will cause the HTTPS binding of the other site to be unusable. Do you still want to continue?
--------------------------- Yes No ---------------------------
This message tells me that https://bbb.my-domain.com and https://ccc.my-domain.com will become unusable. And I will have downtime for those at least until I'm done replacing the certificate for those 2 domains too, right?
I was thinking that there must be a smarter way of doing this. Possibly through the command line that replaces the wildcard certificate with a new one for all website at once. I couldn't find any resources online as to how to do that. Any ideas?
Sites related to wildcard and binding:
Sites related to binding certificates from the command line:
The context of the answer is that IIS 7 doesn't actually care about the certificate binding. IIS 7 only ties websites to one or more sockets. Each socket being a combination of IP + port. Source: IIS7 add certificate to site from command line
So, what we want to do is do certificate re-binding on the OS layer. The OS layer takes control of the SSL part, so you use netsh
to associate a certificate with a particular socket. This is done through netsh
using netsh http add sslcert
.
When we bind a (new) certificate to a socket (ip + port), all sites using that socket will use the new certificate.
The command to bind a certificate to a socket is:
netsh http add sslcert ipport=10.100.0.12:443 certhash=1234567890123456789012345678901234567890 appid={12345678-1234-1234-1234-999999999999}
This part explains how to proceed step-by-step. It assumes you have some websites (aaa.my-domain.com, bbb.my-domain.com) running a *.my-domain.com certificate that is about to expire. You already have a new certificate that you already installed on the server but not yet applied to the websites on IIS.
First, we need to find out 2 things. The certhash of your new certificate and the appid.
certhash
Specifies the SHA hash of the certificate. This hash is 20 bytes long and specified as a hexadecimal string.
appid
Specifies the GUID to identify the owning application, which is IIS itself.
Find the certhash
Execute the certutil
command to get all certificates on the machine:
certutil -store My
I need not all information so I do:
certutil -store My | findstr /R "sha1 my-domain.com ===="
Among the output you should find your new certificate ready on your server:
================ Certificate 5 ================
Subject: CN=*.my-domain.com, OU=PositiveSSL Wildcard, OU=Domain Control Validated
Cert Hash(sha1): 12 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 34 56 78 90
1234567890123456789012345678901234567890
is the certhash
we were looking for. it's the Cert Hash(sha1) without the spaces.
Find the appid
Let's start of by looking at all certificate-socket bindings:
netsh http show sslcert
Or one socket in particular
netsh http show sslcert ipport=10.100.0.12:443
Output:
SSL Certificate bindings:
----------------------
IP:port : 10.100.0.12:443
Certificate Hash : 1111111111111111111111111111111111111111
Application ID : {12345678-1234-1234-1234-123456789012}
Certificate Store Name : MY
Verify Client Certificate Revocation : Enabled
Verify Revocation Using Cached Client Certificate Only : Disabled
Usage Check : Enabled
Revocation Freshness Time : 0
URL Retrieval Timeout : 0
Ctl Identifier : (null)
Ctl Store Name : (null)
DS Mapper Usage : Disabled
Negotiate Client Certificate : Disabled
{12345678-1234-1234-1234-123456789012}
is the appid
we were looking for. It's the Application ID of IIS itself. Here you see the socket 10.100.0.12:443
is currently still bound to the old certificate (Hash 111111111...)
bind a (new) certificate to a socket
Open a command prompt and run it as a administrator. If you don't run it as administrator, you'll get an error like: "The requested operation requires elevation (Run as administrator)."
First remove the current certificate-socket binding using this command
netsh http delete sslcert ipport=10.100.0.12:443
You should get:
SSL Certificate successfully deleted
Then use this command (found here) to add the new certificate-socket binding with the appid and the certhash (without spaces) that you found earlier using this command
netsh http add sslcert ipport=10.100.0.12:443 certhash=1234567890123456789012345678901234567890 appid={12345678-1234-1234-1234-123456789012}
You should get:
SSL Certificate successfully added
DONE. You just replaced the certificate of all websites that are binded to this IP + port (socket).