How to Install and Update Root CA Certificates on Windows Server After Microsoft WSUS Removal


2 views

Since Microsoft discontinued root certificate updates via WSUS in January 2013 (KB931125), administrators face certificate validation issues on fresh Windows Server installations. The default certificate store in Windows Server 2012 contains only Microsoft's own CAs, causing HTTPS communication failures with most public endpoints.

For servers behind SSL termination points (like load balancers), we can bypass the 16KB SChannel limitation by manually installing certificates:

# PowerShell: Install certificate from file
$Cert = Get-PfxCertificate -FilePath "C:\certs\rootCA.cer"
Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath $Cert

For enterprise environments, consider these approaches:

Option 1: Microsoft's Certificate Update Tool

# Download from Microsoft Update Catalog
wget https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB931125

Option 2: Mozilla's CA Bundle

# Convert Mozilla's PEM bundle to Windows format
openssl x509 -inform PEM -in cacert.pem -outform DER -out mozilla.cer
certutil -addstore -f "Root" mozilla.cer

Implement a scheduled task to keep certificates updated:

# PowerShell maintenance script
$UpdateURL = "https://curl.se/ca/cacert.pem"
$LocalPath = "$env:TEMP\cacert.pem"
Invoke-WebRequest -Uri $UpdateURL -OutFile $LocalPath
# Conversion and import logic here

After installation, verify with:

# Check installed root certificates
Get-ChildItem -Path Cert:\LocalMachine\Root | 
    Where-Object { $_.Subject -match "CA" } | 
    Select-Object Subject, Thumbprint

For specific website testing:

# Test HTTPS connection
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
try {
    $Request = [System.Net.WebRequest]::Create("https://target.site")
    $Request.GetResponse()
    $Request.ServicePoint.Certificate
} finally {
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
}

Since Microsoft stopped pushing root certificate updates via WSUS in January 2013, many administrators face certificate validation issues - especially on fresh Windows Server 2012 installations. The default certificate store contains only Microsoft's own CAs, causing HTTPS connections to fail when accessing services secured by other certificate authorities.

Here are three reliable approaches to populate your server's certificate store:

Method 1: Using certmgr.msc

# PowerShell command to launch Certificate Manager
Start-Process certmgr.msc

Navigate to "Trusted Root Certification Authorities" > "Certificates" and import needed certificates.

Method 2: PowerShell Automation

# Example: Importing DigiCert root certificate
$certUrl = "https://cacerts.digicert.com/DigiCertGlobalRootCA.crt"
$certPath = "$env:TEMP\DigiCertGlobalRootCA.crt"
Invoke-WebRequest -Uri $certUrl -OutFile $certPath
Import-Certificate -FilePath $certPath -CertStoreLocation Cert:\LocalMachine\Root

Method 3: Certificate Bundle from Mozilla

The Mozilla CA Certificate Store provides a comprehensive collection:

# Download and extract Mozilla's CA bundle
$mozUrl = "https://curl.se/ca/cacert.pem"
$output = "$env:TEMP\cacert.pem"
Invoke-WebRequest -Uri $mozUrl -OutFile $output

For ongoing maintenance, consider these strategies:

  • Create a scheduled task to periodically check for updates from major CAs
  • Implement a Group Policy for enterprise environments
  • Use configuration management tools like Ansible or Puppet

After installing certificates, verify with:

# Test SSL connectivity
Test-NetConnection -ComputerName example.com -Port 443

# Check certificate chain
openssl s_client -connect example.com:443 -showcerts

For large-scale deployments:

# Sample DSC configuration for certificate deployment
Configuration DeployRootCerts {
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    Node "WebServer*" {
        Script ImportRootCert {
            GetScript = { @{ Result = (Get-ChildItem Cert:\LocalMachine\Root | Measure-Object).Count } }
            SetScript = {
                $certUrl = "https://example.com/root.crt"
                $certPath = "$env:TEMP\root.crt"
                Invoke-WebRequest -Uri $certUrl -OutFile $certPath
                Import-Certificate -FilePath $certPath -CertStoreLocation Cert:\LocalMachine\Root
            }
            TestScript = {
                $cert = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Thumbprint -eq "ABC123..." }
                return ($null -ne $cert)
            }
        }
    }
}