From e9fc284dcb8a02ee659223d6e9d612114a067efb Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 1 May 2026 11:50:04 -0400 Subject: [PATCH] Restore-UDCData: mount share with SFLD creds instead of raw UNC from SYSTEM Symptom: every Restore-UDCData log entry showed bay-level files as 'absent' even when they actually existed on the share - on a device where another PC's run had successfully consumed and migrated the same backup. Endless 'no work this cycle' loop on the device that should have done the consume. Cause: script ran as NT AUTHORITY\SYSTEM (manifest engine on logon). SYSTEM authenticates to remote SMB as the COMPUTER ACCOUNT (DOMAIN\HOSTNAME$), not as a user. The SFLD share's ACL grants top-level enumeration to authenticated computers (so Test-Path on share root + bay dir returned True) but file-level read only to the SFLD user. With no explicit user creds, Test-Path on bay-level files returns False - indistinguishable from 'file not found' - so the script silently logged 'absent' on files that actually exist. A different PC with proper creds consumed bay 3207 first; ours kept polling forever. Update-MachineNumber.ps1's branch already worked around this by calling Mount-SFLDShare (Restore-EDncReg.ps1's helper that reads HKLM:\SOFTWARE\GE\SFLD\Credentials\* and net-use's the share with the SFLD user identity). Fix: Restore-UDCData.ps1 now does the same. Replaces raw-UNC Test-Path polling with Mount-SFLDShare, probes via the W: drive letter, and unmounts on every exit path. If creds are missing in registry the script fails fast with a clear ERROR rather than masquerading as 'no backup'. --- .../Standard/Restore-UDCData.ps1 | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/playbook/shopfloor-setup/Standard/Restore-UDCData.ps1 b/playbook/shopfloor-setup/Standard/Restore-UDCData.ps1 index 30650e2..12aff62 100644 --- a/playbook/shopfloor-setup/Standard/Restore-UDCData.ps1 +++ b/playbook/shopfloor-setup/Standard/Restore-UDCData.ps1 @@ -126,32 +126,42 @@ if (-not $mn -or $mn -eq '9999' -or $mn -notmatch '^\d+$') { exit 0 } -# -- Wait for the share to be reachable --------------------------------- -# When this script runs early in a logon (e.g. via GE-Enforce on autologon), -# the SFLD share via the SMB redirector can take 20-60 seconds to become -# reachable, especially in SYSTEM context where the credential is the -# computer account. Poll until reachable or timeout before deciding "no backup". -Log "Polling share root for reachability: $BackupShareRoot" -$shareReachable = $false +# -- Mount share with SFLD user creds ----------------------------------- +# This script runs as NT AUTHORITY\SYSTEM (manifest engine on logon, or +# scheduled task). SYSTEM authenticates to remote SMB as the COMPUTER +# ACCOUNT (DOMAIN\HOSTNAME$), not as a user. The SFLD share's ACLs grant +# top-level enumeration to authenticated computers but file-level read +# only to a specific SFLD user. Without explicit user creds, Test-Path +# on bay-level files returns False (access denied = same return as not- +# found), making the script silently log "absent" when the files in fact +# exist. Symptom: Restore-UDCData.log shows endless "no work this cycle" +# while another PC (or a user-context invocation) successfully consumes +# the backup. Fix: mount the share with explicit SFLD creds from +# HKLM:\SOFTWARE\GE\SFLD\Credentials and probe via the drive letter. +. (Join-Path $PSScriptRoot '..\Shopfloor\lib\Restore-EDncReg.ps1') + +Log "Mounting share with SFLD creds: $BackupShareRoot -> W:" +$shareMounted = $false $sw = [Diagnostics.Stopwatch]::StartNew() while ($sw.Elapsed.TotalSeconds -lt $ShareTimeoutSec) { - if (Test-Path -LiteralPath $BackupShareRoot) { - $shareReachable = $true + if (Mount-SFLDShare -SharePath $BackupShareRoot -DriveLetter 'W:') { + $shareMounted = $true break } Start-Sleep -Seconds $SharePollSec } $sw.Stop() -if ($shareReachable) { - Log ("Share reachable after {0:N1} s" -f $sw.Elapsed.TotalSeconds) +if ($shareMounted) { + Log ("Share mounted as W: after {0:N1} s" -f $sw.Elapsed.TotalSeconds) } else { - Log "Share NOT reachable after $ShareTimeoutSec s. Cannot probe for backup. Exiting non-zero so the dispatcher logs a failure." 'ERROR' + Log "Mount-SFLDShare failed after $ShareTimeoutSec s. SFLD creds may be missing in HKLM:\SOFTWARE\GE\SFLD\Credentials, or the share is unreachable. Exiting non-zero so the dispatcher logs a failure." 'ERROR' Log 'Exit 1.' exit 1 } -# -- Probe for a waiting backup ------------------------------------------ -$bayDir = Join-Path $BackupShareRoot $mn +# All bay-level paths now go through W: (authenticated as SFLD user) so +# Test-Path returns the truth, not access-denied-False. +$bayDir = Join-Path 'W:\' $mn $srcCur = Join-Path $bayDir 'CurrentData.json' $srcArc = Join-Path $bayDir 'ArchivedData' Log "Probing backup paths for bay $mn" @@ -165,6 +175,7 @@ Log " ArchivedData/ src: $(if ($srcArcExists) { 'present' } else { 'absent' if (-not $srcCurExists -and -not $srcArcExists) { Log "No backup waiting for bay $mn (neither CurrentData.json nor ArchivedData\ at bay root) - no work to do this cycle." + & net use W: /delete /y 2>$null | Out-Null Log 'Exit 0.' exit 0 } @@ -202,6 +213,7 @@ if (-not (Test-Path -LiteralPath $UdcDataDir)) { } catch { Log "Failed to create $UdcDataDir - cannot continue" 'ERROR' LogErr $_ + & net use W: /delete /y 2>$null | Out-Null Log 'Exit 1.' exit 1 } @@ -325,6 +337,9 @@ if ((Test-Path -LiteralPath $UdcExePath) -and ($copiedCur -or $copiedArc)) { } } +# Unmount the SFLD-creds-mounted drive so we don't leave a stale net-use entry +& net use W: /delete /y 2>$null | Out-Null + Log 'Exit 0.' Log '===============================================' exit 0