I think I understand, but I want to be sure.
We are running two Windows 2016 domain controllers (VMs), one of which is performing the role of a certificate server. We perform system state backups daily and offload them to a remote location. If, for whatever reason, the Domain Controller with the CA needs to be completely rebuilt, I assume I can do a non-authoritative restore using the most recent system state backup to recover the CA and the existing domain controller will update the rebuilt server with all other AD information. Is this a correct assumption or should I implement a CA specific recovery plan?
Additional Information: I am working on a baseline for a system deployed in 50+ disconnected environments. Adding another server to each site is not an option for me at this point. I plan on implementing both system state and a CA specific backup plan to aid in recovery, here are a few scripts I scrapped together to aid in manual checks and automated daily processes.
#CA Initial / Update Backup Script
$filedate = (Get-Date -format d).ToString().Replace(“/”,”-“)
#Backup / verify backup
IF ((Test-Path D:\CAbackup) -eq $False)
{
mkdir D:\CABackup
mkdir D:\CABackup\InitialBackup
Backup-CARoleService -KeyOnly D:\CABackup\InitialBackup -Password (read-host -Prompt "Assign a password for the CA Private Key" -AsSecureString)
Backup-CARoleService -DatabaseOnly D:\CABackup\InitialBackup
reg export HKLM\System\CurrentControlSet\Services\CertSvc\Configuration D:\CABackup\InitialBackUp\<filename>.reg
}
ELSEIF ((Test-Path D:\CABackup\InitialBackup) -eq $False)
{
mkdir D:\CABackup\InitialBackup
Backup-CARoleService -KeyOnly D:\CABackup\InitialBackup -Password (read-host -Prompt "Assign a password for the CA Private Key" -AsSecureString)
Backup-CARoleService -DatabaseOnly D:\CABackup\InitialBackup
reg export HKLM\System\CurrentControlSet\Services\CertSvc\Configuration D:\CABackup\InitialBackUp\<filename>.reg
}
ELSE {
IF ((Test-Path D:\CABackup\InitialBackup\database\<filename>.edb) -eq $false)
{
Backup-CARoleService -DatabaseOnly D:\CABackup\InitialBackup
}
ELSE {}
IF ((Test-Path D:\CABackup\InitialBackup\<filename>.reg) -eq $false)
{
reg export HKLM\System\CurrentControlSet\Services\CertSvc\Configuration D:\CABackup\InitialBackUp\<filename>.reg
}
ELSE {}
IF ((Test-Path D:\CABackup\InitialBackup\<filename>.p12) -eq $false)
{
Backup-CARoleService -KeyOnly D:\CABackup\InitialBackup -Password (read-host -Prompt "Assign a password for the CA Private Key" -AsSecureString)
}
ELSE
{
#Compare the backed up certificate thumbprint against the CA certificate thumbprint, if they do not match, archive the old cert and back up the current one
$catpret = certutil -adca | Select-String "Cert Hash"
$catp = $certret.Line.Substring(17)
$archtp = (Get-PfxData -FilePath d:\cabackup\Prikey\<filename>.p12).EndEntityCertificates.Thumbprint
IF ($catp -ne $archtp)
{
mv d:\cabackup\prikey\<filename>.p12 d:\cabackup\prikey\<filename>.p12.$filedate
Backup-CARoleService -DatabaseOnly D:\CABackup\InitialBackup
}
ELSE {}
}
}
#List of certificates that will expire in next 120 days
$list=@()
$na =(get-date).addDays(120)
$listofexp = certutil -view -restrict "NotAfter<=$na" -out "RequestID,RequesterName,Request Common Name,NotAfter"
$total = ($listofexp.count -10)
$f=10
$e=13
While ($e -lt $total)
{
$list += ($listofexp[$f] + $listofexp[$f+1] + $listofexp[$f+2] + $listofexp[$e])
$f = $f+6
$e = $e+6
}
#Daily backup
$filedate = (Get-Date -format d).ToString().Replace(“/”,”-“)
mkdir D:\CABackup\$filedate
Backup-CARoleService -DatabaseOnly D:\CABackup\$filedate
reg export HKLM\System\CurrentControlSet\Services\CertSvc\Configuration D:\CABackup\$fildate\<filename>.reg
#Clear 2 week and older cert requests
$list=@()
$setpurge = (get-date).AddDays(-14)
$purgedate = Get-date $setpurge -Format "MM/dd/yy"
$listofpend = certutil -view -restrict "Request Submission Date<=$purgedate,Request Disposition=9" -out "Request ID, Request Submission Date, Request Common Name"
$total = ($listofpend.count -9)
$f=9
$e=11
While ($e -lt $total)
{
$list += ($listofpend[$f] -replace '.*\(' -replace '\),*')
$f = $f+5
$e = $e+5
}
foreach ($item in $list)
{
certutil -deleterow $item
}
<#Original purge process replaced by above
$setpurge = (get-date).AddDays(-14)
$purgedate = Get-date $setpurge -Format "MM/dd/yy"
certutil -deleterow $purgedate request
#>
I have tested most of this out in a lab and am letting the dailies run for a bit before I delete a server or two and attempt restoration. If anyone has any additional advice it would be greatly appreciated.