Base script
parent
646f35e53b
commit
9cb93c2386
|
|
@ -0,0 +1,348 @@
|
|||
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory)][String] $Action,
|
||||
[Parameter(Mandatory)][String] $Path,
|
||||
[String] $RecipientKeyName,
|
||||
[String] $TransferFileName,
|
||||
[String] $ReconcileFileName = "##protect_transfer_reconcile##.csv",
|
||||
[String] $SecretFileName = ".\transfer.key",
|
||||
[switch] $ExcludeHash,
|
||||
[switch] $Install7zip
|
||||
)
|
||||
|
||||
$default_dateLocal = Get-Date -Format "yyyyMMdd_HHmm"
|
||||
$default_reconcileFile = "##protect_transfer_reconcile##.csv"
|
||||
$default_secretEncrypted = ".\transfer.key"
|
||||
|
||||
|
||||
function Write-Log {
|
||||
param(
|
||||
[String] $LogEntry
|
||||
)
|
||||
|
||||
$date = Get-Date -f "yyyy-MM-dd"
|
||||
|
||||
$logPath = Join-Path -Path ".\" -ChildPath "Logs"
|
||||
$logName = "protect_transfer_reconcile_$date.log"
|
||||
$sFullPath = Join-Path -Path $logPath -ChildPath $logName
|
||||
|
||||
if (!(Test-Path -Path $logPath)) {
|
||||
$null = New-Item -Path $logPath -ItemType Directory
|
||||
}
|
||||
|
||||
if (!(Test-Path -Path $sFullPath)) {
|
||||
Write-Host "Log path: $sFullPath"
|
||||
$null = New-Item -Path $sFullPath -ItemType File
|
||||
}
|
||||
$dateTime = Get-Date -f "yyyy-MM-dd HH:mm:ss"
|
||||
Add-Content -Path $sFullPath -Value "[$dateTime]. $LogEntry"
|
||||
|
||||
}
|
||||
|
||||
function Close-Log {
|
||||
$dateTime = Get-Date -f "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Log "***********************************************************************************"
|
||||
Write-Log "* End of processing: [$dateTime]"
|
||||
Write-Log "***********************************************************************************"
|
||||
}
|
||||
|
||||
function New-RandomPassword {
|
||||
param(
|
||||
[int]$length = 20,
|
||||
[String]$characters = "abcdefghiklmnoprstuvwxyzABCDEFGHKLMNOPRSTUVWXYZ1234567890!()?}][{@#*+-",
|
||||
[switch]$ConvertToSecureString
|
||||
)
|
||||
$password = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
|
||||
$private:ofs=""
|
||||
|
||||
if ($ConvertToSecureString.IsPresent) {
|
||||
return ConvertTo-SecureString -String [String]$characters[$password] -AsPlainText -Force
|
||||
} else {
|
||||
return [String]$characters[$password]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Reconcile
|
||||
function Set-Reconcile
|
||||
{
|
||||
Param(
|
||||
[Parameter(Mandatory)][String] $ReconcileFile,
|
||||
[Parameter(Mandatory)][String] $FolderName,
|
||||
[switch]$Feedback = $false
|
||||
)
|
||||
|
||||
if ($reconcileFile -eq "")
|
||||
{
|
||||
$reconcileFile = $default_reconcileFile
|
||||
}
|
||||
|
||||
If (!(Test-Path -Path $folderName )) {
|
||||
Write-Log "Folder '$folderName' does not exist"
|
||||
Write-Host "Folder '$folderName' does not exist" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
|
||||
Write-Log "Generating reconciliation file '$reconcileFile'"
|
||||
Write-Host "Generating reconciliation file '$reconcileFile'"
|
||||
|
||||
$totalFileCount = 0
|
||||
$totalFileSize = 0
|
||||
|
||||
Set-Content -Path $reconcileFile -Value '"FullName","LastWriteTime","Length","Hash","ParentFolder","Object"'
|
||||
Get-Childitem $folderName -Recurse | Where-Object {!$_.PSIsContainer} | ForEach-Object {
|
||||
$totalFilecount = $totalFileCount + 1
|
||||
$totalFileSize = $totalFileSize + $_.Length
|
||||
if ($ExcludeHash) {
|
||||
$sourceHash = ""
|
||||
} else {
|
||||
$sourceHash = (Get-FileHash -Path $_.FullName).Hash
|
||||
}
|
||||
$record = '"'+$_.FullName.Replace($folderName, "")+'","'+$_.LastWriteTime.ToString("yyyy-MM-ddTHH:mm:ss")+'",'+$_.Length+',"'+$sourceHash+'","'+ $_.Directory + '","' + $_.Name + '"'
|
||||
Add-Content -Path $reconcileFile -Value $record
|
||||
}
|
||||
|
||||
if ($totalFileSize -ge 1000000000000) {
|
||||
$totalRightLabel = "TB"
|
||||
$totalFileXbytes = [math]::Round(($totalFileSize / 1000000000000), 2)
|
||||
} else {
|
||||
if ($totalFileSize -ge 1000000000) {
|
||||
$totalRightLabel = "GB"
|
||||
$totalFileXbytes = [math]::Round(($totalFileSize / 1000000000), 2)
|
||||
} else {
|
||||
if ($totalFileSize -ge 1000000) {
|
||||
$totalRightLabel = "MB"
|
||||
$totalFileXbytes = [math]::Round(($totalFileSize / 1000000), 2)
|
||||
} else {
|
||||
$totalRightLabel = "KB"
|
||||
$totalFileXbytes = [math]::Round(($totalFileSize / 1000), 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Total reconcile file count is $totalFileCount and size $totalFileXbytes $totalRightLabel"
|
||||
if ($feedback) {
|
||||
Write-Host "Total reconcile file count is $totalFileCount and size $totalFileXbytes $totalRightLabel" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Invoke-Pack
|
||||
{
|
||||
Param(
|
||||
[String] $TransferFolder,
|
||||
[String] $ToName,
|
||||
[String] $CompressFile,
|
||||
[String] $ReconcileFile,
|
||||
[String] $SecretEncrypted
|
||||
)
|
||||
# Send
|
||||
If (!(Test-Path -Path $transferFolder )) {
|
||||
Write-Log "Folder '$transferFolder' does not exist"
|
||||
Write-Host "Folder '$transferFolder' does not exist" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Write-Log "Packing files to compress file '$compressFile'"
|
||||
Write-Log "Source folder is '$transferFolder'"
|
||||
Write-Host "Packing files to compress file '$compressFile'"
|
||||
|
||||
if ($reconcileFile -eq "")
|
||||
{
|
||||
$reconcileFile = $default_reconcileFile
|
||||
}
|
||||
|
||||
if ($secretEncrypted -eq "")
|
||||
{
|
||||
$secretEncrypted = $default_secretEncrypted
|
||||
}
|
||||
|
||||
# First step - create protected secret
|
||||
$secret = New-RandomPassword -Length 80
|
||||
Protect-CmsMessage -To $toName -OutFile $secretEncrypted -Content $secret
|
||||
|
||||
# Second step - compress the data files
|
||||
Compress-7Zip -Path $transferFolder -ArchiveFileName $compressFile -Format SevenZip
|
||||
|
||||
# Third step - create the reconcile file
|
||||
Set-Reconcile -ReconcileFile $reconcileFile -FolderName $transferFolder
|
||||
|
||||
# Fourth step - add reconcile file to ZIP and encrypt
|
||||
Write-Log "Add reconcile file '$reconcileFile' to file '$compressFile'"
|
||||
$fullReconcileName = (Get-Item $reconcileFile).FullName
|
||||
$fullZipName = (Get-Item $compressFile).FullName
|
||||
Compress-7Zip -Path $fullReconcileName -ArchiveFileName $fullZipName -Format SevenZip -Append -Password $secret -EncryptFilenames
|
||||
Remove-Item $fullReconcileName
|
||||
Write-Log "Package ready in file '$compressFile' from folder '$transferFolder'"
|
||||
Write-Host "Package ready in file '$compressFile' from folder '$transferFolder'" -ForegroundColor Green
|
||||
}
|
||||
|
||||
|
||||
function Invoke-Unpack
|
||||
{
|
||||
Param(
|
||||
[String] $RestoreFolder,
|
||||
[String] $ToName,
|
||||
[String] $CompressFile,
|
||||
[String] $SecretEncrypted
|
||||
)
|
||||
# Receive
|
||||
If (!(Test-Path -Path $CompressFile )) {
|
||||
Write-Log "Transfer/compress file '$CompressFile' does not exist"
|
||||
Write-Host "Transfer/compress file '$CompressFile' does not exist" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
|
||||
if ($secretEncrypted -eq "")
|
||||
{
|
||||
$secretEncrypted = $default_secretEncrypted
|
||||
}
|
||||
|
||||
# First step - decrypt password for uncompressing
|
||||
Write-Log "Restoring files transferred to '$restoreFolder'"
|
||||
Write-Log "Package/Compress file is '$compressFile'"
|
||||
$secret = Unprotect-CmsMessage -To $toName -Path $secretEncrypted
|
||||
|
||||
# Second step - uncompress the data files
|
||||
Expand-7Zip -ArchiveFileName $compressFile -TargetPath $restoreFolder -Password $secret
|
||||
Write-Log "Package unpacked from file '$compressFile' to folder '$restoreFolder'"
|
||||
Write-Host "Package unpacked from file '$compressFile' to folder '$restoreFolder'" -ForegroundColor Green
|
||||
}
|
||||
|
||||
|
||||
# Reconcile
|
||||
function Invoke-Reconcile
|
||||
{
|
||||
Param(
|
||||
[Parameter(Mandatory)][String] $reconcileFileName,
|
||||
[Parameter(Mandatory)][String] $folderName
|
||||
)
|
||||
|
||||
Write-Log "Reconciling documents transferred"
|
||||
Write-Host "Reconciling documents transferred"
|
||||
If (!(Test-Path -Path $reconcileFileName )) {
|
||||
Write-Log "Reconciliation file '$reconcileFileName' does not exist"
|
||||
Write-Host "Reconciliation file '$reconcileFileName' does not exist" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
If (!(Test-Path -Path $folderName )) {
|
||||
Write-Log "Folder '$folderName' does not exist"
|
||||
Write-Host "Folder '$folderName' does not exist" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
Write-Log "Using reconciliation file '$reconcileFileName'"
|
||||
|
||||
$totalFilecount = 0
|
||||
$errorCount = 0
|
||||
|
||||
# For each entry in the reconcile file
|
||||
# find the file and compare hash
|
||||
Import-Csv $reconcileFileName | ForEach-Object {
|
||||
$totalFileCount = $totalFileCount +1
|
||||
$restoreFileName = $(Join-Path -Path $folderName -ChildPath $_.FullName)
|
||||
If (Test-Path -Path $restoreFileName ) {
|
||||
$targetHash= (Get-FileHash -Path $restoreFileName).Hash
|
||||
if ($_.Hash -ne $targetHash) {
|
||||
$errorCount = $errorCount + 1
|
||||
Write-Log "Hash mismatch for file '$restoreFileName'"
|
||||
}
|
||||
if ((Get-Item -Path $restoreFileName).LastWriteTime.ToString("yyyy-MM-ddTHH:mm:ss") -ne $_.LastWriteTime) {
|
||||
$errorCount = $errorCount + 1
|
||||
Write-Log "Last write mismatch for file '$restoreFileName'"
|
||||
}
|
||||
|
||||
} else {
|
||||
$errorCount = $errorCount + 1
|
||||
Write-Log "Non existant target file '$restoreFileName'"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Total file count is $totalFileCount with $errorCount errors"
|
||||
if ($errorCount -gt 0) {
|
||||
Write-Host "Total file count is $totalFileCount with $errorCount errors" -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host "Total file count is $totalFileCount with $errorCount errors" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
$dateTimeStart = Get-Date -f "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Log "***********************************************************************************"
|
||||
Write-Log "* Start of processing: [$dateTimeStart]"
|
||||
Write-Log "***********************************************************************************"
|
||||
|
||||
if ($install7zip) {
|
||||
Install-Module -Name 7Zip4Powershell -Scope CurrentUser
|
||||
}
|
||||
|
||||
$actioned = $false
|
||||
|
||||
if ($action -eq "Pack") {
|
||||
$actioned = $true
|
||||
if ($RecipientKeyName -eq "") {
|
||||
Write-Log "Recipient Key Name required for packing"
|
||||
Write-Host "Recipient Key Name required for packing" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
|
||||
if ($TransferFileName -eq "") {
|
||||
$TransferFileName = ".\transfer_protect_$default_dateLocal.7z"
|
||||
}
|
||||
|
||||
Invoke-Pack -TransferFolder $path -ToName $recipientKeyName -CompressFile $transferFileName -ReconcileFile $reconcileFileName -SecretEncrypted $secretFileName
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($action -eq "Unpack") {
|
||||
$actioned = $true
|
||||
if ($RecipientKeyName -eq "") {
|
||||
Write-Log "Recipient Key Name required for unpacking"
|
||||
Write-Host "Recipient Key Name required for unpacking" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
if ($TransferFileName -eq "") {
|
||||
Write-Log "Transfer/Compress File Name required for unpacking"
|
||||
Write-Host "Transfer/Compress File Name required for unpacking" -ForegroundColor Red
|
||||
Close-Log
|
||||
return
|
||||
}
|
||||
|
||||
Invoke-Unpack -RestoreFolder $path -ToName $recipientKeyName -CompressFile $transferFileName
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($action -eq "ReconcileFile") {
|
||||
$actioned = $true
|
||||
Set-Reconcile -ReconcileFile $reconcileFileName -FolderName $path -Feedback
|
||||
}
|
||||
|
||||
|
||||
if ($action -eq "Reconcile") {
|
||||
$actioned = $true
|
||||
$localReconcileFile = Join-Path -Path $path -ChildPath $reconcileFileName
|
||||
Invoke-Reconcile -ReconcileFile $localReconcileFile -FolderName $path
|
||||
}
|
||||
|
||||
|
||||
if (!($actioned))
|
||||
{
|
||||
Write-Log "Unknown action '$action'. No processing performed"
|
||||
Write-Host "Unknown action '$action'. No processing performed" -ForegroundColor Red
|
||||
Write-Host "Recognised actions: "
|
||||
Write-Host " Pack : Pack folder contents into secure 7Zip file"
|
||||
Write-Host " Unpack : Unpack folder contents from secure 7Zip file"
|
||||
Write-Host " Reconcile : Reconcile files in unpack folder with list of packed files"
|
||||
Write-Host " ReconcileFile : Generate a reconcile file without packing"
|
||||
}
|
||||
|
||||
Close-Log
|
||||
Loading…
Reference in New Issue