aethercert
Documentation

Replace a Certificate in the Windows Certificate Store

Import a PFX into the Local Computer store with Import-PfxCertificate, confirm HasPrivateKey, grant private-key access and verify every service that uses it.

The Windows certificate store is a repository, not a TLS endpoint. Importing a new certificate makes it available to Windows services, but does not make IIS, RDP, SQL Server, or another application use it. Each consumer still needs its own binding or thumbprint updated.

Before you begin

  • Obtain a PKCS#12/PFX containing the leaf certificate and matching private key, plus its password. If the PFX does not contain the intermediate CA certificates, import them into Intermediate Certification Authorities as well.
  • Confirm the certificate has the required DNS SANs, Enhanced Key Usage, validity, and key algorithm for its consumer.
  • Record the old certificate thumbprint and every service that references it.
  • Use an elevated session. Most server applications require Cert:\LocalMachine\My, not the interactive user's CurrentUser store.

Understand how Windows stores certificates

LocalMachine\My is the computer's Personal store. The certificate entry points to a private-key container protected by Windows ACLs. Importing as an administrator does not automatically give an arbitrary service account permission to use that key. Manage Private Keys in the Certificates MMC snap-in is therefore an operational part of replacement for services that do not run as Local System.

Step-by-step certificate replacement

  1. Inspect the PFX without exposing its password in shell history:

    $pfxPath = "C:\secure\replacement.pfx"
    $pfxPassword = Read-Host "PFX password" -AsSecureString
    Get-PfxData -FilePath $pfxPath -Password $pfxPassword |
      Format-List EndEntityCertificates,OtherCertificates
  2. Import it into the Local Computer Personal store:

    $imported = Import-PfxCertificate `
      -FilePath $pfxPath `
      -CertStoreLocation Cert:\LocalMachine\My `
      -Password $pfxPassword
    $thumbprint = $imported.Thumbprint

    Add -Exportable only when later re-export is an explicit requirement; it weakens a useful protection on the private key.

  3. Confirm the private key and chain:

    Get-Item "Cert:\LocalMachine\My\$thumbprint" |
      Format-List Subject,DnsNameList,NotAfter,EnhancedKeyUsageList,HasPrivateKey,Thumbprint
    Export-Certificate -Cert "Cert:\LocalMachine\My\$thumbprint" -FilePath C:\Temp\new.cer
    certutil -verify -urlfetch C:\Temp\new.cer

    HasPrivateKey must be True. certutil -verify -urlfetch builds the chain and checks revocation; it needs a certificate file, hence the export.

  4. If the consuming Windows service uses a dedicated identity, open certlm.msc (the console for the computer's certificates), select Personal > Certificates, right-click the new certificate, then choose All Tasks > Manage Private Keys. Add the service account (for a virtual account such as NT SERVICE\<service>, type it as shown) and allow Read only, not Full Control.

  5. Update the consumer's certificate setting or binding. Use the dedicated guide for IIS, AD FS, SQL Server, or the other product. Restart or reload only that product when its procedure requires it.

Clusters and Group Policy

The same certificate may be installed on multiple cluster nodes, but the private key and certificate-store entry are local to each node. Import it on every node that can terminate TLS. A Group Policy certificate distribution mechanism generally distributes public certificates and trust anchors; do not assume it distributes a server's private key.

Verify the new certificate

Verify both layers. First inspect the local store as above. Then connect to the actual hostname and port, because a healthy store says nothing about the active binding. The script below deliberately accepts any certificate ({$true}) - it is meant to show what the service presents, not to judge trust:

$client = [Net.Sockets.TcpClient]::new("service.example.com",443)
$stream = [Net.Security.SslStream]::new($client.GetStream(),$false,({$true}))
$stream.AuthenticateAsClient("service.example.com")
[Security.Cryptography.X509Certificates.X509Certificate2]::new($stream.RemoteCertificate) |
  Format-List Subject,Issuer,Thumbprint,NotAfter
$stream.Dispose(); $client.Dispose()

Rollback

The store itself needs no rollback: the old certificate stays in it until you delete it. Point the consuming service back to the recorded old thumbprint, following that product's guide - for example the binding in IIS - and do whatever the product needs to use it (a reload or restart). Do not delete the new entry until the rollback is confirmed.

Common problems

  • The PFX was imported into CurrentUser instead of LocalMachine.
  • HasPrivateKey is False because only a .cer file was imported. Import the PFX instead. If the matching key is already on the machine, certutil -repairstore my <serial-number> can re-link certificate and key.
  • The service identity cannot read the key container.
  • The chain is incomplete or its root is not trusted by clients.
  • The correct certificate is installed but the application still references the old thumbprint.

Automating certificate replacement with aethercert

aethercert can import the certificate and private key into the selected Windows store. For product presets it can also perform the supported binding or assignment step; a plain Certificate store target intentionally creates no application binding.

See Deploy targets for the fields this preset takes, what it needs on the host, and how far it has been verified.

Sources

On this page