Replace wildcard certificate on multiple sites at once (using command line) on IIS 7.5

Solution 1:

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}

How to

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).