diff --git a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Backup-FormtracepakSettings.ps1 b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Backup-FormtracepakSettings.ps1 index b6986b0..d481f0b 100755 --- a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Backup-FormtracepakSettings.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Backup-FormtracepakSettings.ps1 @@ -221,18 +221,32 @@ function Copy-ToStaging { } Copy-Item -Path $f.FullName -Destination $destFull -Force $counters[$CounterKey]++ - - $manifestRows.Add([PSCustomObject]@{ - RelativePath = $destRelPath - OriginalPath = $f.FullName - SizeBytes = $f.Length - LastModified = $f.LastWriteTime.ToString('o') - Hash = (Get-FileHash $f.FullName -Algorithm MD5 -ErrorAction SilentlyContinue).Hash - }) } catch { Write-Warning " Failed to copy $($f.FullName): $_" $counters.Errors++ + continue } + + # Hash computation runs in its own try so a hash failure (e.g. FIPS + # policy banning MD5, missing file, permission) does NOT roll back + # the copy we just succeeded at. SHA256 is the default and is + # FIPS-compliant; older Backup runs may have written MD5 hashes + # into file_manifest.csv but Install never reads those - it computes + # fresh hashes at restore time for the [SKIP] Identical check. + $hash = $null + try { + $hash = (Get-FileHash -LiteralPath $f.FullName -Algorithm SHA256 -ErrorAction Stop).Hash + } catch { + Write-Warning " Hash skipped for $($f.FullName): $_" + } + + $manifestRows.Add([PSCustomObject]@{ + RelativePath = $destRelPath + OriginalPath = $f.FullName + SizeBytes = $f.Length + LastModified = $f.LastWriteTime.ToString('o') + Hash = $hash + }) } } diff --git a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Install-FormtracepakSettings.ps1 b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Install-FormtracepakSettings.ps1 index 8de70fc..409436c 100755 --- a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Install-FormtracepakSettings.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Install-FormtracepakSettings.ps1 @@ -212,9 +212,19 @@ function Restore-FileItem { } if ((Test-Path $DestFile) -and -not $Force) { - $srcHash = (Get-FileHash $SourceFile -Algorithm MD5).Hash - $destHash = (Get-FileHash $DestFile -Algorithm MD5).Hash - if ($srcHash -eq $destHash) { + # SHA256 not MD5: MD5 throws under Windows FIPS policy + # ("This implementation is not part of the Windows Platform FIPS + # validated cryptographic algorithms"). SHA256 is FIPS-compliant + # and is Get-FileHash's default. + $srcHash = $null + $destHash = $null + try { + $srcHash = (Get-FileHash -LiteralPath $SourceFile -Algorithm SHA256 -ErrorAction Stop).Hash + $destHash = (Get-FileHash -LiteralPath $DestFile -Algorithm SHA256 -ErrorAction Stop).Hash + } catch { + Write-Warning " Hash compare failed for ${DestFile}: $_ - falling through to overwrite" + } + if ($srcHash -and $destHash -and $srcHash -eq $destHash) { Write-Host " [SKIP] Identical: $DestFile" -ForegroundColor DarkGray $counters.Skipped++ return