Last active
October 30, 2016 01:19
-
-
Save GrantTrebbin/595b48fd1fe65351b178048282553934 to your computer and use it in GitHub Desktop.
Create encrypted and compressed backups only when warranted
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Backs up and encrypts a directory or file | |
.DESCRIPTION | |
Backs up files or directories by adding it them a tar file and then | |
encrypting it with a public key. Becuase public key encryption is used | |
there are no passwords stored anywhere. | |
gpg must be installed and the public key you want to use must be imported. | |
Encrypted items will keep their orignal name but have the following | |
added to the start YYYYMMDD_XXXXXXXX_ and .tar.gpg added to the end. | |
YYYYMMDD represents the date and XXXXXXXX represents the fingerprint | |
(last 8 hex characters) of a hash created with DirHash. | |
i.e. test.txt may become | |
20161029_A4F88BC1_test.txt.tar.gpg | |
The encryption process also compresses the data first. It is set to zlib | |
level 9. This is maximum compression. You may want to change it | |
If an encrypted backup with the same original name and fingerprint exists, | |
the file will not be updated. If an encrypted backup with the same name | |
and a different fingerprint exists, it will be deleted and a new backup | |
created. This is because if the fingerprints are different the files have | |
changed and the backup needs to be updated. | |
If an origal file is deleted, the encrypted backup will not be delted. | |
.PARAMETER | |
None | |
.INPUTS | |
None | |
.OUTPUTS | |
Items backed up will be written the console | |
.NOTES | |
Version: 1.0 | |
Author: Grant Trebbin | |
Creation Date: 29/10/2016 | |
Purpose/Change: Initial Script | |
#> | |
# Fill these variables with the required parameters | |
$pathToBackup = "" | |
$outputLocation = "" | |
$public_key_fingerprint = "" | |
function New-TemporaryDirectory{ | |
# Create a new temporary directory in the system | |
# temporary location and return its full path | |
$parent = [System.IO.Path]::GetTempPath() | |
# Create a directory name and make sure it doesn't exist | |
do{ | |
[string] $name = [System.Guid]::NewGuid() | |
} while ((Test-Path (Join-Path $parent $name))) | |
# Create a directory and return its name | |
$newPath = Join-Path $parent $name | |
New-Item -ItemType Directory -Path $newPath > $null | |
return $newPath | |
} | |
$date = Get-Date | |
$dateString = $date.ToString("yyyyMMdd") | |
$temporaryLocation = New-TemporaryDirectory | |
$items = Get-ChildItem -Path $pathToBackup -Filter "" -Force| Select FullName | |
ForEach($item in $items){ | |
# Get the name of each item | |
$itemName = (Get-Item -Force $item.FullName) | |
$leafItemName = Split-Path -Path $item.FullName -Leaf | |
# Get the hash of the item | |
$itemHash = D:\Grant\Projects\Scripts\DirHash.ps1 -Path $itemName.FullName | |
# Get the fingerprint of the hash (last 8 characters) | |
$itemFingerPrint = $itemHash.substring($itemHash.length -8, 8) | |
# Generate FileNames | |
# Filename will take the form | |
# YYYYMMDD_<8 character hex fingerprint>_<original item name>.tar.gpg | |
$tarName = $leafItemName + '.tar' | |
$fingerPrintFileName = "_" + $itemFingerPrint + "_"+ $tarName + '.gpg' | |
$encryptedFileName = $dateString + $fingerPrintFileName | |
# See if a matching backup already exists | |
$backupNameWildcard = | |
Join-Path $outputLocation ("********" + $fingerPrintFileName) | |
$doesBackupExist = (Test-Path($backupNameWildcard)) | |
if ($doesBackupExist -eq $false){ | |
# Find OldBackup if one already exists | |
# Only check if original file names match | |
$oldBackupWildcard = | |
Join-Path $outputLocation ("******_********_" + $tarName + ".gpg") | |
$oldBackups = Get-ChildItem -Path $oldBackupWildcard -Force | |
# Tar the file or directory to archive and add the .tar extension | |
$tarFile = Join-Path $temporaryLocation $tarName | |
cmd /c 7z.exe a -ttar $tarFile $itemName.FullName > $null 2>&1 | |
# Encrypt the file | |
# The file is redirected in and out of the gpg command because it | |
# doesn't seem to handle unicode filenames. The filenames in the | |
# command need to be surrounded by quotes in case the filename | |
# contains a space. | |
$encryptedFilePath = Join-Path $temporaryLocation $encryptedFileName | |
$encryptionCommand = "gpg -o- --batch -r " + $public_key_fingerprint + | |
" -z 9 --encrypt" + " < `"" + $tarFile + "`"" + " > `"" + | |
$encryptedFilePath + "`"" | |
cmd /c $encryptionCommand | |
# The redirection causes a problem though. If the encryption process | |
# fails for any reason it still writes the output file, it's just | |
# empty. That's why the encrypted file is written to the temporary | |
# directory. The new encrypted backup is moved into the ouptut | |
# directory and the old backups are deleted only if $LASTEXITCODE | |
# equals zero indicating that the gpg command has succeeded | |
if ($LASTEXITCODE -eq 0){ | |
Move-Item $encryptedFilePath ( | |
Join-Path $outputLocation $encryptedFileName) | |
foreach($test in $oldBackups){ | |
Remove-Item ($test) | |
} | |
# Write status message | |
Write-Host ("Backing up " + $leafItemName + | |
" to " + $encryptedFileName) | |
} | |
# Remove the temporary tar file | |
Remove-Item $tarFile | |
} | |
} | |
Remove-Item $temporaryLocation -Recurse |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment