In my last blog post (Backing up ADCS Certificate Authorities Part 1) I covered the inner workings of how ADCS and the Jet database works to maintain the CA data. In this post I am going to go over a comprehensive PowerShell script that I wrote to perform a full backup of all necessary ADCS components. In addition, this backup will ensure the CA performs the necessary log maintenance and truncation that I indicated was vital in Part 1.

A customer recently tasked me with improving my old batch backup script. The batch file lacked any command arguments, diagnostic reporting, event monitoring and script statuses. To properly implement this in an enterprise, customers needed a stronger backup script.

Download CA Backup Script

    This script is capable of backing up the following data:

    • ADCS Certificate Authority database
    • CA certificates, including previously renewed CA certificates
    • CA Configuration data stored in the registry
    • Thales nCipher HSM configuration and key files
    • List of published templates available on the CA

    Details about the script

    • The script is not signed at this point, you can either sign it or temporarily change the execution level to allow it to run
    • The first time you use the script, you need to register the script so that it creates the event log source CABackup in the Application Log. The syntax is “.\cabackup.ps1 -Register $True”. You will need to be a local admin
    • There are a few switches to use as arguments. The most important might be the “EventLogging” so information goes into the Application Event Log, source CABackup.
      • Event IDs to watch:
        • Event 1, Backup Started
        • Event 2, Backup Completed Successfully,
        • Events 3,4 (Error) are problems with aspects in backing up the CA and should be alerted on
    • Argument BackupFolder allows you to specify where backups go, by default it is c:\cabackups


    #Specifies the destiniation backup folder
    #Determines if Thales HSM Files should be backedup
    #Enables diagnostic logging
    #Enables Event Log Entries
    #Used during install to register the eventlog source

    Scripted by: Mark B. Cooper
    PKI Solutions Inc.
    Version: 1.2
    Date: October 18, 2019

    function WriteDebugLog ([string]$msg)
    $(Get-Date -format ‘MM-dd-yy hh:mm:ss’) +”: ” + $msg | Out-File -FilePath $logfile -Append
    if ($Diagnostic)
    Write-Host $msg
    function WriteEventLog ([string]$msg, [int]$EventID,[bool]$Error)
    if ($EventLogging)
    if ($Error)
    Write-EventLog -LogName Application -Source “CABackup” -EventId $EventID -EntryType Error -Message $msg -Category 0
    Write-EventLog -LogName Application -Source “CABackup” -EventId $EventID -EntryType Information -Message $msg -Category 0
    Set-PSDebug -Trace 0
    Revision and Log detail tracking purposes only
    Log and temp files
    $logfile = “$BackupFolder\Backup-Log-$(Get-Date -format ‘yyyy-MM-dd’).log”
    if ($Register)
    New-EventLog -LogName “Application” -Source “CABackup”
    if (Test-Path $BackupFolder)
    New-Item $BackupFolder -ItemType Directory | Out-Null
    WriteDebugLog “Script Starting -Version $ScriptVersion”
    Write-Host “Starting Certification Authority Backup…”
    WriteEventLog “Starting Certification Authority Backup” 1
    WriteDebugLog “Removing Backup Folder Contents”
    Remove-Item $BackupFolder* -Recurse
    WriteDebugLog “Error removing old backup folder contents. Error: ” + $error[0]
    Write-Host “Unable to empty the target backup folder. Script is ending”
    WriteEventLog “Unable to empty the target backup folder. Script is ending” 3 $true
    WriteDebugLog “Backup Folder Prepared”
    WriteDebugLog “Backing Up CA Database”
    Backup-CARoleService -path $BackupFolder -DatabaseOnly
    WriteDebugLog “Error Performing CA Database Backup. Error: ” + $error[0]
    Write-Host “Unable to perform CA Database Backup. Script is ending”
    WriteEventLog “Unable to perform CA Database Backup. Script is ending” 4 $true
    WriteDebugLog “CA Database backup completed”
    WriteDebugLog “Copying CA Certificates”
    Copy-Item $env:windir\System32\Certsrv\CertEnroll*.crt $BackupFolder
    WriteDebugLog “Error Copying CA Certificate Files. Error: ” + $error[0]
    #Not considered a critical error, so backup will continue
    WriteDebugLog “CA certificates backup completed.”
    WriteDebugLog “Copying CAPolicy.inf”
    if (Test-Path $env:windir\capolicy.inf) {
    Copy-Item $env:windir\capolicy.inf $BackupFolder
    WriteDebugLog “Error Copying CAPolicy File. Error: ” + $error[0]
    #Not considered a critical error, so backup will continue
    WriteDebugLog “CAPolicy.inf backup completed.”
    WriteDebugLog “Exporting CA Registry Configuration”
    &’reg.exe’ “export” “HKLM\system\currentcontrolset\services\certsvc\configuration” $BackupFolder\caregistry.reg
    if ($ThalesHSM)
    WriteDebugLog “Backing up Thales HSM Files”
    Get-ChildItem $env:nfast_kmdata -Directory | Where-Object{$_.Name -ne “tmp”} | Copy-Item -Destination $BackupFolder\HSM -Recurse -Force
    WriteDebugLog “Error Copying Thales HSM Files. Error: ” + $error[0]
    #Not considered a critical error, so backup will continue
    WriteDebugLog “Checking CA Type to determine if an Issuing CA”
    $activeConfig = get-itemproperty -path “HKLM:\System\CurrentControlSet\Services\CertSvc\configuration” -Name active
    $activeConfig = $activeConfig.Active
    $CAType = get-itemproperty -path HKLM:\System\CurrentControlSet\Services\CertSvc\configuration\$activeConfig -Name CAType
    if ($CAType.CAType -eq “1”)
    WriteDebugLog “CA is an Issuing CA – Dumping list of templates”
    certutil –catemplates > $BackupFolder\CATemplates.txt
    WriteDebugLog “Backup Completed.”
    Write-Host “Certification Authority Backup COMPLETED”
    WriteEventLog “Certification Authority Backup COMPLETED” 2


    About ThePKIGuy

    President & Founder at PKI Solutions, Leading PKI Cybersecurity Subject Matter Expert, Author, Speaker, Trainer, Microsoft Certified Master.


    1. ThePKIGuy ThePKIGuy on October 18, 2019 at 8:47 am

      Just updated the script to account for an issue where the installation of nCipher KeySafe can cause the backup of the KMDATA folder can fail.

    2. Avatar Greg on March 14, 2020 at 9:17 pm

      Remove ” from certutil -“catemplates > $BackupFolder\CATemplates.txt

      • ThePKIGuy ThePKIGuy on March 16, 2020 at 8:12 am

        Good catch. An updated version of the script is being uploaded now. Version 1.3

    3. Avatar Dennis Ervin on April 13, 2020 at 8:26 am

      Thanks for an excellent article and script. If we wanted to setup a scheduled task for this script to run every few months, would it be able to work under local system, or does it need real user credentials?


      • ThePKIGuy ThePKIGuy on April 13, 2020 at 12:41 pm

        We always recommend a service account as it can be tracked and audited. The account would need Backup Operator rights.

    4. Avatar CL on July 8, 2020 at 7:33 am

      Do you have a restore script available similar to the backup?

      • ThePKIGuy ThePKIGuy on July 8, 2020 at 7:37 am

        Unfortunately no, there are many nuances to performing a restore. Other than just removing templates, restoring database, adding templates, there is a lot to do with restoring missing certificates (if any) that occurred after the backup was performed. Also, given the very seldom need for restore/recovery, it’s not a common request.

        • Avatar CL on July 8, 2020 at 7:43 am

          The specific case I am looking at is for the Root CA

    5. Avatar Veera kumar on August 2, 2020 at 9:10 am

      Does this Script require/perform stop and restart or ADCS service while taking backup??

      • ThePKIGuy ThePKIGuy on August 2, 2020 at 9:11 am

        No stop/restart is performed as part of this script.

    6. Avatar Roshan Raikar on August 9, 2020 at 11:03 am

      I loved the article and the script. i also admire how you used event logs to log the events of this backup cycle. Kudos

    Leave a Comment

    This site uses Akismet to reduce spam. Learn how your comment data is processed.