Files
pxe-server/playbook/shopfloor-setup/gea-shopfloor-collections/Set-ControllerCredential.ps1
cproudlock 27045d5e4a gea-shopfloor-collections: controller NIC auto-IP + credential break-glass
04-SetControllerNicIP.ps1 (imaging-time, runs once via Run-ShopfloorSetup):
- Finds the Realtek physical Ethernet adapter (controller NIC on every
  collections bay; corp LAN is Intel)
- Skips any candidate with a DHCP default gateway (that one is the corp
  LAN, not the controller)
- Skips any candidate already on 192.168.1.2
- Sets static 192.168.1.2/24, no gateway, clears DNS - matches the
  manual procedure documented in post-deploy-debug-flowchart.md section 2B
- Refuses to guess when multiple Realtek NICs remain ambiguous
- Imaging-time only, not enforced via GE-Enforce so the tech can override
  on a specific bay if needed without the drift-catcher reverting

Set-ControllerCredential.ps1 + manifest-entry-controller-credential.json:
- Break-glass cmdkey /add for the controller SMB share (\\192.168.1.1\md1
  used by DNC). Scoped to the 12 Okuma LOC650 machine numbers (3201-3212).
- Manifest entry is detection-less so it runs every enforce cycle if the
  script is armed (.ps1 extension); disarmed by default (.ps1.bak on the
  share) so a coach can rename when a bay loses its credential without
  the enforcer overwriting per-bay deviations between events.
- Smoke-tested end-to-end on win11 VM via QGA: SYSTEM context cmdkey /add
  succeeds, cmdkey /list shows the entry. DNC service runs as LocalSystem
  so SYSTEM vault is the right target.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:38:59 -04:00

83 lines
3.3 KiB
PowerShell

# Set-ControllerCredential.ps1 - Self-heal a Windows Credential Manager
# entry for the controller's NIC subnet (default 192.168.1.1). Re-applied
# every GE-Enforce cycle so the entry survives any Defender / policy
# blowaway between cycles.
#
# Why: collections bays periodically lose the controller credential from
# Credential Manager (cause TBD - suspect Defender / Intune scrub). Without
# the cred, controller-side connections need interactive prompts. Restoring
# it on each enforce cycle keeps the bay working unattended.
#
# Wiring: pointed to by gea-shopfloor-collections\manifest.json on the SFLD
# share. GE-Enforce calls this directly via the Install-FromManifest PS1
# action type. Idempotent - cmdkey /add overwrites silently if the entry
# already exists.
#
# Edit the three values below to set the actual credential, then push the
# manifest entry to the SFLD share (see README in same dir).
#
# Log: C:\Logs\Shopfloor\controller-credential.log
$ErrorActionPreference = 'Continue'
# --- EDIT THESE THREE VALUES ---
$Target = '192.168.1.1' # Controller IP or hostname
$Username = 'CHANGEME' # Controller-side username
$Password = 'CHANGEME' # Controller-side password
# --- END EDIT ---
$logDir = 'C:\Logs\Shopfloor'
if (-not (Test-Path $logDir)) {
try { New-Item -Path $logDir -ItemType Directory -Force | Out-Null } catch { $logDir = $env:TEMP }
}
$logFile = Join-Path $logDir 'controller-credential.log'
function Write-CredLog {
param([string]$Message, [string]$Level = 'INFO')
$line = '[{0}] [{1}] [{2}] {3}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $env:USERNAME, $Message
Add-Content -Path $logFile -Value $line -ErrorAction SilentlyContinue
Write-Host $line
}
Write-CredLog "=== Set-ControllerCredential start (target=$Target) ==="
if ($Username -eq 'CHANGEME' -or $Password -eq 'CHANGEME') {
Write-CredLog 'Credential placeholders not filled in - refusing to write CHANGEME values' 'ERROR'
exit 1
}
# Check current state. cmdkey /list output for a missing target returns
# 'Currently stored credentials: ... NONE' or omits the target.
$listOut = & cmdkey /list:$Target 2>&1 | Out-String
if ($listOut -match [regex]::Escape("Target: $Target")) {
Write-CredLog "Entry for $Target already present in Credential Manager - re-applying anyway (cmdkey /add updates idempotently)"
} else {
Write-CredLog "No entry for $Target found in Credential Manager - adding"
}
# cmdkey /add expects /generic for non-domain creds (SMB / RDP / SQL).
# Use /add: for plain network credential (matches the older 'net use'
# style cred used by NET shares + most non-AD apps). Switch to /generic:
# if the target is HTTP / RDP TERMSRV-specific.
& cmdkey /add:$Target /user:$Username /pass:$Password 2>&1 | ForEach-Object {
Write-CredLog " cmdkey: $_"
}
$rc = $LASTEXITCODE
if ($rc -eq 0) {
Write-CredLog "cmdkey /add succeeded (target=$Target user=$Username)"
} else {
Write-CredLog "cmdkey /add failed (exit $rc)" 'ERROR'
exit $rc
}
# Quick verify
$verify = & cmdkey /list:$Target 2>&1 | Out-String
if ($verify -match [regex]::Escape("Target: $Target")) {
Write-CredLog 'Verification passed - entry present after add'
} else {
Write-CredLog 'Verification FAILED - entry not visible after add' 'WARN'
}
Write-CredLog '=== Set-ControllerCredential end ==='
exit 0