Configure-PC + nocollections ACL: align with two-task machine number design
- gea-shopfloor-nocollections/02-MachineNumberACLs.ps1: gut to no-op matching the collections variant. SYSTEM Apply task no longer needs per-user ACLs on the eDNC reg key or UDC ProgramData dir. - Configure-PC.ps1 item 6 (Machine number logon prompt toggle): Stop duplicating Register-ScheduledTask logic inline. Call the shared Register-CheckMachineNumberTask.ps1 registrar so both the Prompt user-task and Apply SYSTEM-task are installed with matching SDDL config. Existence check now treats EITHER the new "Prompt Machine Number" task OR the legacy "Check Machine Number" task as "ON" so old bays still register correctly. Toggle OFF unregisters all three names (Prompt + Apply + legacy) for clean removal.
This commit is contained in:
@@ -285,8 +285,13 @@ if ($null -ne $cfgItems -and $cfgItems.Count -gt 0) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Machine-number logon task is item 6
|
# Machine-number logon tasks (item 6 toggle controls both)
|
||||||
$machineNumTaskName = 'Check Machine Number'
|
# 2026-05-24: split into user-context Prompt + SYSTEM-context Apply.
|
||||||
|
# 'Check Machine Number' is the legacy single-task name kept for
|
||||||
|
# backward-detection on bays imaged before the split.
|
||||||
|
$machineNumPromptTask = 'Prompt Machine Number'
|
||||||
|
$machineNumApplyTask = 'Apply Machine Number'
|
||||||
|
$machineNumLegacyTask = 'Check Machine Number'
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Interactive UI
|
# Interactive UI
|
||||||
@@ -354,8 +359,12 @@ foreach ($item in $items) {
|
|||||||
Write-Host " $($item.Num). $on $($item.Label) - $($item.Detail)$avail"
|
Write-Host " $($item.Num). $on $($item.Label) - $($item.Detail)$avail"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Item 6: machine number logon prompt
|
# Item 6: machine number logon prompt. "ON" if EITHER the new Prompt task OR
|
||||||
$machineNumTaskExists = [bool](Get-ScheduledTask -TaskName $machineNumTaskName -ErrorAction SilentlyContinue)
|
# the legacy Check Machine Number task is registered.
|
||||||
|
$machineNumTaskExists = [bool](
|
||||||
|
(Get-ScheduledTask -TaskName $machineNumPromptTask -ErrorAction SilentlyContinue) -or
|
||||||
|
(Get-ScheduledTask -TaskName $machineNumLegacyTask -ErrorAction SilentlyContinue)
|
||||||
|
)
|
||||||
$mnOn = if ($machineNumTaskExists) { '[ON]' } else { '[ ]' }
|
$mnOn = if ($machineNumTaskExists) { '[ON]' } else { '[ ]' }
|
||||||
Write-Host " 6. $mnOn Prompt standard user for machine number if 9999"
|
Write-Host " 6. $mnOn Prompt standard user for machine number if 9999"
|
||||||
|
|
||||||
@@ -419,62 +428,47 @@ if ($selection) {
|
|||||||
# Process item 6: machine number logon task
|
# Process item 6: machine number logon task
|
||||||
if ($selected -contains 6) {
|
if ($selected -contains 6) {
|
||||||
if ($machineNumTaskExists) {
|
if ($machineNumTaskExists) {
|
||||||
# Toggle OFF
|
# Toggle OFF - remove Prompt + Apply (new design) AND the legacy
|
||||||
|
# Check Machine Number task name (in case this bay was imaged
|
||||||
|
# before the split and never re-imaged).
|
||||||
|
$removed = @()
|
||||||
|
foreach ($t in @($machineNumPromptTask, $machineNumApplyTask, $machineNumLegacyTask)) {
|
||||||
try {
|
try {
|
||||||
Unregister-ScheduledTask -TaskName $machineNumTaskName -Confirm:$false -ErrorAction Stop
|
if (Get-ScheduledTask -TaskName $t -ErrorAction SilentlyContinue) {
|
||||||
Write-Host " Machine number logon prompt: REMOVED" -ForegroundColor Yellow
|
Unregister-ScheduledTask -TaskName $t -Confirm:$false -ErrorAction Stop
|
||||||
|
$removed += $t
|
||||||
|
}
|
||||||
|
} catch { Write-Warning " Failed to remove '$t': $_" }
|
||||||
|
}
|
||||||
|
if ($removed) {
|
||||||
|
Write-Host " Machine number logon prompt: REMOVED ($($removed -join ', '))" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
$machineNumTaskExists = $false
|
$machineNumTaskExists = $false
|
||||||
} catch { Write-Warning " Failed to remove task: $_" }
|
|
||||||
} else {
|
} else {
|
||||||
# Toggle ON - register logon task
|
# Toggle ON - register logon task
|
||||||
# The task needs to run as the logged-in user (for GUI), but
|
# Defer task registration to the shared registrar so this code
|
||||||
# writing to HKLM + ProgramData requires the ACLs we pre-grant
|
# path always matches the imaging-time path. Registrar installs
|
||||||
# during imaging (see task 7 / ACL pre-grant script).
|
# BOTH the user-context "Prompt Machine Number" task and the
|
||||||
|
# SYSTEM-context "Apply Machine Number" task, sets the SDDL on
|
||||||
|
# Apply so Limited users can schtasks /run it, and cleans up
|
||||||
|
# any legacy "Check Machine Number" task name.
|
||||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
$checkScript = Join-Path $scriptDir 'Check-MachineNumber.ps1'
|
$registrar = Join-Path $scriptDir 'Register-CheckMachineNumberTask.ps1'
|
||||||
|
if (-not (Test-Path -LiteralPath $registrar)) {
|
||||||
if (-not (Test-Path -LiteralPath $checkScript)) {
|
$registrar = 'C:\Enrollment\shopfloor-setup\Shopfloor\Register-CheckMachineNumberTask.ps1'
|
||||||
# Fallback: check enrollment staging dir
|
|
||||||
$checkScript = 'C:\Enrollment\shopfloor-setup\Shopfloor\Check-MachineNumber.ps1'
|
|
||||||
}
|
}
|
||||||
|
if (Test-Path -LiteralPath $registrar) {
|
||||||
if (Test-Path -LiteralPath $checkScript) {
|
|
||||||
try {
|
try {
|
||||||
$action = New-ScheduledTaskAction `
|
& $registrar
|
||||||
-Execute 'powershell.exe' `
|
|
||||||
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Normal -File `"$checkScript`""
|
|
||||||
|
|
||||||
$trigger = New-ScheduledTaskTrigger -AtLogOn
|
|
||||||
|
|
||||||
# Run as the logged-in user (needs GUI for InputBox), NOT
|
|
||||||
# SYSTEM (SYSTEM can't show UI to the user's desktop).
|
|
||||||
$principal = New-ScheduledTaskPrincipal `
|
|
||||||
-GroupId 'S-1-5-32-545' `
|
|
||||||
-RunLevel Limited
|
|
||||||
|
|
||||||
$settings = New-ScheduledTaskSettingsSet `
|
|
||||||
-AllowStartIfOnBatteries `
|
|
||||||
-DontStopIfGoingOnBatteries `
|
|
||||||
-StartWhenAvailable `
|
|
||||||
-ExecutionTimeLimit (New-TimeSpan -Minutes 5)
|
|
||||||
|
|
||||||
Register-ScheduledTask `
|
|
||||||
-TaskName $machineNumTaskName `
|
|
||||||
-Action $action `
|
|
||||||
-Trigger $trigger `
|
|
||||||
-Principal $principal `
|
|
||||||
-Settings $settings `
|
|
||||||
-Force `
|
|
||||||
-ErrorAction Stop | Out-Null
|
|
||||||
|
|
||||||
Write-Host " Machine number logon prompt: ENABLED" -ForegroundColor Green
|
Write-Host " Machine number logon prompt: ENABLED" -ForegroundColor Green
|
||||||
Write-Host " (will auto-disable after machine number is set)" -ForegroundColor DarkGray
|
Write-Host " (Prompt user-task + Apply SYSTEM-task registered;" -ForegroundColor DarkGray
|
||||||
|
Write-Host " will auto-disable after machine number is set)" -ForegroundColor DarkGray
|
||||||
$machineNumTaskExists = $true
|
$machineNumTaskExists = $true
|
||||||
} catch {
|
} catch {
|
||||||
Write-Warning " Failed to register task: $_"
|
Write-Warning " Register-CheckMachineNumberTask failed: $_"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Warning " Check-MachineNumber.ps1 not found at $checkScript"
|
Write-Warning " Register-CheckMachineNumberTask.ps1 not found at $registrar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,29 @@
|
|||||||
# 02-MachineNumberACLs.ps1 - Pre-grant write access on the UDC settings
|
# 02-MachineNumberACLs.ps1 - NO-OP (deprecated 2026-05-24).
|
||||||
# file and eDNC registry key so that STANDARD (non-admin) users can update
|
|
||||||
# the machine number via the Check-MachineNumber logon task without
|
|
||||||
# elevation or a UAC prompt.
|
|
||||||
#
|
#
|
||||||
# Runs during imaging as admin (type-specific Standard phase, after
|
# This script used to grant BUILTIN\Users SetValue on the eDNC reg key
|
||||||
# 01-eDNC.ps1 has installed DnC). Only touches Standard PCs.
|
# and Modify on the UDC ProgramData dir so the logged-in user could
|
||||||
|
# update machine number from the Check-MachineNumber logon dialog without
|
||||||
|
# elevation.
|
||||||
#
|
#
|
||||||
# What gets opened up (narrow scope, not blanket admin):
|
# That design had two flaws:
|
||||||
# - C:\ProgramData\UDC\udc_settings.json -> BUILTIN\Users : Modify
|
# 1. Security hole - any logged-in user could overwrite the machine-
|
||||||
# - HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General
|
# identity reg key.
|
||||||
# -> BUILTIN\Users : SetValue
|
# 2. Fragile - ACL grants raced with eDNC install timing on some bays;
|
||||||
|
# the OpenSubKey call returned null + the grant was silently skipped,
|
||||||
|
# leaving Check-MachineNumber unable to update the bay (yet the old
|
||||||
|
# Update-MachineNumber.ps1 reported success anyway because
|
||||||
|
# Set-ItemProperty's PermissionDenied is non-terminating).
|
||||||
|
#
|
||||||
|
# Replaced by the two-task design in Register-CheckMachineNumberTask.ps1:
|
||||||
|
# - "Prompt Machine Number" : user-context GUI, no privileges
|
||||||
|
# - "Apply Machine Number" : SYSTEM-context worker, full HKLM access
|
||||||
|
#
|
||||||
|
# Left as a no-op so Stage-Dispatcher / Run-ShopfloorSetup discovery
|
||||||
|
# patterns don't have to be updated. Existing bays' ACL grants are still
|
||||||
|
# present and harmless (the SYSTEM Apply task ignores them).
|
||||||
|
|
||||||
# --- Transcript ---
|
|
||||||
$logDir = 'C:\Logs\SFLD'
|
$logDir = 'C:\Logs\SFLD'
|
||||||
if (-not (Test-Path $logDir)) { try { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } catch {} }
|
if (-not (Test-Path $logDir)) { try { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } catch {} }
|
||||||
try { Start-Transcript -Path (Join-Path $logDir '02-MachineNumberACLs.log') -Append -Force | Out-Null } catch {}
|
try { Start-Transcript -Path (Join-Path $logDir '02-MachineNumberACLs.log') -Append -Force | Out-Null } catch {}
|
||||||
|
Write-Host "02-MachineNumberACLs.ps1: no-op (replaced by SYSTEM Apply task - see Register-CheckMachineNumberTask.ps1)"
|
||||||
# --- Skip on Timeclock sub-type (no UDC/eDNC to grant ACLs for) ---
|
|
||||||
$subtypeFile = 'C:\Enrollment\pc-subtype.txt'
|
|
||||||
if (Test-Path $subtypeFile) {
|
|
||||||
$subtype = (Get-Content $subtypeFile -First 1 -ErrorAction SilentlyContinue).Trim()
|
|
||||||
if ($subtype -eq 'Timeclock') {
|
|
||||||
Write-Host "02-MachineNumberACLs: skipped (Standard-Timeclock)"
|
|
||||||
try { Stop-Transcript | Out-Null } catch {}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "02-MachineNumberACLs.ps1 starting $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
|
||||||
Write-Host "Running as: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
|
|
||||||
Write-Host ""
|
|
||||||
Write-Host "Setting ACLs for standard-user machine number access..."
|
|
||||||
|
|
||||||
# --- UDC settings directory ---
|
|
||||||
# Set ACL on the DIRECTORY (not the file) with inheritance so that
|
|
||||||
# udc_settings.json inherits the permission whenever UDC.exe creates it.
|
|
||||||
# UDC_Setup.exe is killed by KillAfterDetection before UDC.exe writes the
|
|
||||||
# JSON, so the file doesn't exist at this point. Directory-level ACL with
|
|
||||||
# ContainerInherit + ObjectInherit covers any file created inside later.
|
|
||||||
$udcDir = 'C:\ProgramData\UDC'
|
|
||||||
if (Test-Path -LiteralPath $udcDir) {
|
|
||||||
try {
|
|
||||||
$acl = Get-Acl -LiteralPath $udcDir
|
|
||||||
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
|
||||||
'BUILTIN\Users', 'Modify',
|
|
||||||
([System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor
|
|
||||||
[System.Security.AccessControl.InheritanceFlags]::ObjectInherit),
|
|
||||||
[System.Security.AccessControl.PropagationFlags]::None,
|
|
||||||
'Allow')
|
|
||||||
$acl.AddAccessRule($rule)
|
|
||||||
Set-Acl -LiteralPath $udcDir -AclObject $acl -ErrorAction Stop
|
|
||||||
Write-Host " UDC dir: BUILTIN\Users granted Modify (inherited) on $udcDir"
|
|
||||||
} catch {
|
|
||||||
Write-Warning " Failed to set ACL on $udcDir : $_"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-Host " UDC dir not found at $udcDir - skipping (UDC not installed?)" -ForegroundColor DarkGray
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- eDNC registry key ---
|
|
||||||
$ednRegPathWin = 'SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General'
|
|
||||||
try {
|
|
||||||
$regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($ednRegPathWin, $true)
|
|
||||||
if ($regKey) {
|
|
||||||
$regSec = $regKey.GetAccessControl()
|
|
||||||
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(
|
|
||||||
'BUILTIN\Users', 'SetValue', 'Allow')
|
|
||||||
$regSec.AddAccessRule($rule)
|
|
||||||
$regKey.SetAccessControl($regSec)
|
|
||||||
$regKey.Close()
|
|
||||||
Write-Host " eDNC reg: BUILTIN\Users granted SetValue on HKLM:\$ednRegPathWin"
|
|
||||||
} else {
|
|
||||||
Write-Host " eDNC registry key not found - skipping (eDNC not installed?)" -ForegroundColor DarkGray
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
Write-Warning " Failed to set ACL on HKLM:\$ednRegPathWin : $_"
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "ACL setup complete."
|
|
||||||
try { Stop-Transcript | Out-Null } catch {}
|
try { Stop-Transcript | Out-Null } catch {}
|
||||||
|
|||||||
Reference in New Issue
Block a user