13

I'm writing a Powershell script to go through my list of IIS bindings, find any that have a particular 'old' cert thumbprint, and replace their certs with a cert that has a 'new' thumbprint. This is so I can update the certificate for many bindings, because we use the same certificate for a lot of sites so we need to update all bindings that have the old cert to the new cert. Here's what I've come up with:

##### EDIT THESE VARIABLES #####
$SiteName = "movc-website-www"
$OldCertThumbprint = "‎76 ae 0b 2e b9 f7 45 ce 27 c4 02 6e 90 66 62 93 69 d7 5e 4c"
$ReplacementCertThumbprint = "‎7f fa 9f f3 90 b8 a2 d8 4c 98 51 47 a5 64 1d 90 f6 2f ca 73"

##### FUNCTIONS #####
Function ReplaceWebsiteBinding {
    Param(
        [string] $SiteName,
        [string] $OldCertThumbprint,
        [string] $ReplacementCertThumbprint
    );

    Import-Module WebAdministration;

    $ReplacedCount = 0

    $IISBindings = (Get-ItemProperty -Path "IIS:\Sites\$SiteName" -Name Bindings)
    for ($i=0; $i -lt ($IISBindings.Collection).Length; $i++) {
        if (($IISBindings.Collection[$i]).certificateHash -eq $OldCertThumbprint) {
            ($IISBindings.Collection[$i]).RebindSslCertificate($ReplacementCertThumbprint, "My")
            $ReplacedCount++
        }
    }

    Return $ReplacedCount
}

##### MAIN PROGRAM #####
$OldCertThumbprint = $OldCertThumbprint.Replace(" ", "").ToUpper()
$ReplacementCertThumbprint = $ReplacementCertThumbprint.Replace(" ", "").ToUpper()

# Check that cert with given thumbprints exist
$FoundCert = Get-ChildItem -Path Cert:\LocalMachine\My |
    Where-Object { $_.Thumbprint -eq $OldCertThumbprint } |
    Select-Object -ExpandProperty Thumbprint
if (!$FoundCert) {
    Write-Host "Old cert with thumbprint $OldCertThumbprint not found!"
    Exit
}

$FoundCert = Get-ChildItem -Path Cert:\LocalMachine\My |
    Where-Object { $_.Thumbprint -eq $ReplacementCertThumbprint } |
    Select-Object -ExpandProperty Thumbprint

if (!$FoundCert) {
    Write-Host "Replacement cert with thumbprint $ReplacementCertThumbprint not found!"
    Exit
}

# Associate new cert with bindings that have old cert
$ReplacedCount = ReplaceWebsiteBinding $SiteName $OldCertThumbprint $ReplacementCertThumbprint

Write-Host "Replaced $ReplacedCount binding(s)."

The trouble is this doesn't work because the line calling .RebindSslCertificate(...) gives me the following Powershell error:

Value does not fall within the expected range.
At (...)
+             ($IISBindings.Collection[$i]).RebindSslCertificate($Repla ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException

Not the most useful error really, and I can't figure out why I'm getting it. The arguments look OK to me; the thumbprint was found by the Get-ChildItem code and "My" looks fine. The only thing I can think of is that it might be looking in the current user certificate store rather than the local machine certificate store, which is where the desired certs are. Can anyone help me with why this error is happening?

2
  • Your code looks correct. Are you running as Administrator? If you run just the following code are the old and replacement thumbprint / Subject displayed? "$FoundCert = Get-ChildItem -Path Cert:\LocalMachine\My" Commented Jun 11, 2018 at 1:24
  • Yes I am running as Administrator. Yes they are displayed. Commented Jun 11, 2018 at 10:16

2 Answers 2

8

It turns out I was having the same problem as described here (RebindSslCertificate the certificate is just the same as removing it and then calling AddSslCertificate). When copying the thumbprint from the certificate dialog in Windows for some stupid reason it inserts a zero-width LTR character at the beginning of the string so my thumbprint was invalid. I added a check for this at the beginning of my script to prevent it:

if ($OldCertThumbprint -match "[\W-[\ ]]") {
    Write-Host "Old cert thumbprint contains non-word characters, maybe a zero-width LTR Unicode character at the beginning.  You almost certainly don't want this!  Aborting!"
    Exit
}
if ($ReplacementCertThumbprint -match "[\W-[\ ]]") {
    Write-Host "Replacement cert thumbprint contains non-word characters, maybe a zero-width LTR Unicode character at the beginning.  You almost certainly don't want this!  Aborting!"
    Exit
}
Sign up to request clarification or add additional context in comments.

1 Comment

To further bulletproof thumbprint validation, $thumbprint -match '^[a-fA-F0-9]{40}$'. (assuming sha1 hash)
0

I found a great script to "find any [bindings] that have a particular 'old' cert thumbprint, and replace their certs with a cert that has a 'new' thumbprint" here (archived here)

Given the new cert is already installed.

The minimal version is:

$OldThumbprint = "########################################"
$NewThumbprint = "########################################"

Get-WebBinding | Where-Object { $_.certificateHash -eq $OldThumbprint} | ForEach-Object {
    Write-Host "Replacing Cert For "  $_ 
    $_.RemoveSslCertificate()
    $_.AddSslCertificate($NewThumbprint, 'My')
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.