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'.
This commit is contained in:
cproudlock
2026-05-01 11:50:04 -04:00
parent 1ae5bdce57
commit e9fc284dcb

View File

@@ -126,32 +126,42 @@ if (-not $mn -or $mn -eq '9999' -or $mn -notmatch '^\d+$') {
exit 0 exit 0
} }
# -- Wait for the share to be reachable --------------------------------- # -- Mount share with SFLD user creds -----------------------------------
# When this script runs early in a logon (e.g. via GE-Enforce on autologon), # This script runs as NT AUTHORITY\SYSTEM (manifest engine on logon, or
# the SFLD share via the SMB redirector can take 20-60 seconds to become # scheduled task). SYSTEM authenticates to remote SMB as the COMPUTER
# reachable, especially in SYSTEM context where the credential is the # ACCOUNT (DOMAIN\HOSTNAME$), not as a user. The SFLD share's ACLs grant
# computer account. Poll until reachable or timeout before deciding "no backup". # top-level enumeration to authenticated computers but file-level read
Log "Polling share root for reachability: $BackupShareRoot" # only to a specific SFLD user. Without explicit user creds, Test-Path
$shareReachable = $false # 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() $sw = [Diagnostics.Stopwatch]::StartNew()
while ($sw.Elapsed.TotalSeconds -lt $ShareTimeoutSec) { while ($sw.Elapsed.TotalSeconds -lt $ShareTimeoutSec) {
if (Test-Path -LiteralPath $BackupShareRoot) { if (Mount-SFLDShare -SharePath $BackupShareRoot -DriveLetter 'W:') {
$shareReachable = $true $shareMounted = $true
break break
} }
Start-Sleep -Seconds $SharePollSec Start-Sleep -Seconds $SharePollSec
} }
$sw.Stop() $sw.Stop()
if ($shareReachable) { if ($shareMounted) {
Log ("Share reachable after {0:N1} s" -f $sw.Elapsed.TotalSeconds) Log ("Share mounted as W: after {0:N1} s" -f $sw.Elapsed.TotalSeconds)
} else { } 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.' Log 'Exit 1.'
exit 1 exit 1
} }
# -- Probe for a waiting backup ------------------------------------------ # All bay-level paths now go through W: (authenticated as SFLD user) so
$bayDir = Join-Path $BackupShareRoot $mn # Test-Path returns the truth, not access-denied-False.
$bayDir = Join-Path 'W:\' $mn
$srcCur = Join-Path $bayDir 'CurrentData.json' $srcCur = Join-Path $bayDir 'CurrentData.json'
$srcArc = Join-Path $bayDir 'ArchivedData' $srcArc = Join-Path $bayDir 'ArchivedData'
Log "Probing backup paths for bay $mn" 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) { 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." 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.' Log 'Exit 0.'
exit 0 exit 0
} }
@@ -202,6 +213,7 @@ if (-not (Test-Path -LiteralPath $UdcDataDir)) {
} catch { } catch {
Log "Failed to create $UdcDataDir - cannot continue" 'ERROR' Log "Failed to create $UdcDataDir - cannot continue" 'ERROR'
LogErr $_ LogErr $_
& net use W: /delete /y 2>$null | Out-Null
Log 'Exit 1.' Log 'Exit 1.'
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.'
Log '===============================================' Log '==============================================='
exit 0 exit 0