Monday, December 16, 2019

windows server 2008 r2 - Replace wildcard certificate on multiple sites at once (using command line) on IIS 7.5



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:
edit site bindings window in IIS 7.5



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:




Answer



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


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...