public/Backup-CA.ps1
function Backup-CA { <# .SYNOPSIS Backup certificate authority with or without the private key. .DESCRIPTION Creates a folder and backup the Active Directory Certificate Services database to the folder. .PARAMETER Path Backup path. .PARAMETER PrivateKey Backup private key. .EXAMPLE Backup-CA -Path 'C:\Backup'; .EXAMPLE Backup-CA -Path 'C:\Backup' -PrivateKey; #> [cmdletbinding()] [OutputType([pscustomobject])] param ( # Backup path. [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [ValidateScript({ $_ -match '^[a-zA-Z]:\\' })] [ValidateScript({ Test-Path $_ -PathType 'Container' -IsValid })] [string]$Path = $script:ModuleBackupFolder, # Private key backup. [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch]$PrivateKey, # Password for the backup. [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string]$Password ) BEGIN { # Write to log. $customProgress = Write-CustomProgress -Activity $MyInvocation.MyCommand.Name -CurrentOperation 'Backup ADCS database'; # Get disk space. $disksSpace = Get-DiskSpace; # Get database size. $databaseSize = Get-CADatabaseSize; # Get drive letter. $driveLetter = $Path.Substring(0, 2); # Get disk space for drive. $diskSpace = $disksSpace | Where-Object { $_.DriveLetter -eq $driveLetter }; # If disk space is less than database size. if ($diskSpace.FreeSpace -lt $databaseSize.Total) { # Write to event log. Write-CustomEventLog -EventId 1 -AdditionalMessage ('Free space is {0} GB, required space is {1} GB' -f $diskSpace.FreeSpaceInGB, $databaseSize.TotalGb); # Throw exception. throw ('Not enough disk space, free space is {0} GB, required space is {1} GB' -f $diskSpace.FreeSpaceInGB, $databaseSize.TotalGb); } # Else the disk space is enough. else { # Write to log. Write-CustomLog -Message ('Disk space is enough, free space is {0} GB, required space is {1} GB' -f $diskSpace.FreeSpace, $databaseSize.TotalGb) -Level Verbose; } # If the path does not exist. if (-not (Test-Path -Path $Path)) { # Write to log. Write-CustomLog -Message ("Creating backup folder '{0}'" -f $Path) -Level Verbose; # Create the path. $null = New-Item -Path $Path -ItemType 'Directory' -Force; } # Else the path exists. else { # Write to log. Write-CustomLog -Message ("Backup folder '{0}' already exists" -f $Path) -Level Verbose; # If database backup folder already exist. if (Test-Path -Path ('{0}\DataBase' -f $Path)) { # Old database backup folder name. $oldDatabaseBackupFolder = ('DataBase_{0}' -f (Get-Date -Format 'yyyyMMddHHmmss')); # Write to log. Write-CustomLog -Message ("Database backup folder '{0}\DataBase' already exists" -f $Path) -Level Verbose; Write-CustomLog -Message ("Renaming database backup folder '{0}\{1}' already exists" -f $Path, $oldDatabaseBackupFolder) -Level Verbose; # Rename the folder. $null = Rename-Item -Path ('{0}\DataBase' -f $Path) -NewName $oldDatabaseBackupFolder -Force; } } # Get the CertSvc service status. $serviceStatus = Get-CAService; # If the service is not running. if ($serviceStatus -ne 'Running') { # Write to event log. Write-CustomEventLog -EventId 2; # Throw exception. throw ('The CertSvc service is not running. The service must be running to backup the database'); } # Get the common name of the certificate authority. $commonName = Get-CACommonName; # Splatting for the backup. $backupSplat = @{ Path = $Path; ErrorAction = 'Stop'; }; # If the password is set. if (-not [string]::IsNullOrEmpty($Password)) { # Write to log. Write-CustomLog -Message 'Backup will be password protected' -Level Verbose; # Convert the password to a secure string. $securePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force; # Add password to the splat. $null = $backupSplat.Add('Password', $securePassword); } # Object to return. [pscustomobject]$result = [pscustomobject]@{ DatabasePath = ('{0}\DataBase' -f $Path); PrivateKeyPath = $null; }; } PROCESS { # Export CA certificate. $null = Export-CACertificate -FolderPath $Path; # If private key backup is requested. if ($true -eq $PrivateKey) { # Write to event log. Write-CustomEventLog -EventId 12; # If Entrust Security World is installed. if ($true -eq (Test-EntrustSecurityWorldInstalled)) { # Backup Entrust Security World. $entrustSecurityWorld = Backup-EntrustSecurityWorld -Path $Path; # Add member to result. $null = Add-Member -InputObject $result -MemberType NoteProperty -Name 'EntrustSecurityWorldPath' -Value $entrustSecurityWorld.BackupFolderPath -Force; } # Try to backup the private key. try { # Write to log. Write-CustomLog -Message ("Trying to backup the database with private key to the directory '{0}'" -f $Path) -Level Verbose; # Backup the database. Backup-CARoleService @backupSplat; # Write to log. Write-CustomLog -Message ("Successfully made a backup of the database including the private key to the directory '{0}'" -f $Path) -Level Verbose; # Set private key path. $result.PrivateKeyPath = ('{0}\{1}.p12' -f $Path, $commonName); # Write to event log. Write-CustomEventLog -EventId 5; } # Something went wrong. catch { # Write to log. Write-CustomLog -Message ("Failed to backup the database including the private key to the directory '{0}'. Will try without the private key" -f $Path) -Level Warning; # Write to event log. Write-CustomEventLog -EventId 3; # Backup without private key. $null = Backup-CA -Path $Path; } } # Else backup without private key. else { # Write to event log. Write-CustomEventLog -EventId 11; # Try to backup the database. try { # Write to log. Write-CustomLog -Message ("Trying to backup the database without the private key to the directory '{0}'" -f $Path) -Level Verbose; # Backup the database. Backup-CARoleService -DatabaseOnly @backupSplat; # Write to log. Write-CustomLog -Message ("Successfully made a backup of the database without the private key to the directory '{0}'" -f $Path) -Level Verbose; # Write to event log. Write-CustomEventLog -EventId 6; } # Something went wrong. catch { # Write to event log. Write-CustomEventLog -EventId 4; # Throw exception. throw ('Failed to backup the database. {0}' -f $_.Exception.Message); } } } END { # Write to log. Write-CustomProgress @customProgress; # Return result. return $result; } } |