Shopfloor: single autologon, clear Start pins, Intune sync tool, update docs

- AutoLogonCount reduced from 2 to 1 in Run-ShopfloorSetup.ps1
- Remove default pinned Start Menu tiles and set blank layout for future users
- Add sync_intune.bat: triggers MDM sync and polls for SFLD group policies
- Update README.md and SETUP.md with current project state (boot chain, new
  scripts, samba shares, webapp pages, commit history)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-03-31 09:43:00 -04:00
parent 163e58ab0b
commit 9912b044a3
5 changed files with 176 additions and 18 deletions

View File

@@ -15,7 +15,7 @@ Client PXE boot (UEFI Secure Boot)
-> User selects boot option:
├── Windows PE -> wimboot -> boot.wim -> startnet.cmd -> Samba share -> Image deployment
├── Clonezilla -> vmlinuz/initrd -> Disk cloning/imaging
├── Blancco -> vmlinuz/initrd -> NIST 800-88 drive erasure
├── Blancco -> Native kernel + initramfs -> NIST 800-88 drive erasure
└── Memtest86+ -> Memory diagnostics
```
@@ -34,7 +34,7 @@ Client PXE boot (UEFI Secure Boot)
- **PXE server IP:** `10.9.100.1/24`
- **DHCP range:** `10.9.100.10` - `10.9.100.100`
- **Firewall:** UFW deny-by-default, only service ports open
- **Firewall:** UFW deny-by-default, only service ports open (22, 67, 69, 80, 445, 4433, 9009)
## Quick Start
@@ -102,6 +102,8 @@ The Flask webapp (port 9009) provides a browser-based management UI:
- **startnet.cmd Editor** — Modify the startnet.cmd inside boot.wim without Windows (uses wimtools)
- **Clonezilla Backups** — Upload, download, and manage disk backup images
- **Blancco Reports** — View, download, and manage drive erasure reports (auto-collected via Samba)
- **Image Config** — Per-image configuration editor (drivers, OS packages, hardware models)
- **Enrollment** — Upload, download, and manage GCCH bulk enrollment packages
- **Audit Log** — Activity history for all write operations (imports, edits, deletes)
### Image Types Supported
@@ -125,9 +127,15 @@ pxe-server/
│ └── meta-data # Cloud-init metadata (required, empty)
├── playbook/
│ ├── pxe_server_setup.yml # Ansible playbook: all server configuration
── inventory.ini # Ansible inventory
── inventory.ini # Ansible inventory
│ ├── startnet.cmd # WinPE startup script (injected into boot.wim)
│ ├── blancco-init.sh # Custom initramfs for Blancco PXE boot
│ ├── blancco-preferences.xml # Blancco auto-report preferences
│ ├── check-bios.cmd # Pre-imaging BIOS update checker
│ ├── FlatUnattendW10-shopfloor.xml # Shopfloor unattend.xml
│ └── shopfloor-setup/ # PC type setup scripts (Standard, CMM, Display, etc.)
├── webapp/
│ ├── app.py # Flask application (~900 lines)
│ ├── app.py # Flask application (~1600 lines)
│ ├── requirements.txt # Python deps (flask, lxml)
│ ├── static/
│ │ ├── ge-aerospace-logo.svg # GE Aerospace branding
@@ -143,9 +151,13 @@ pxe-server/
│ ├── import.html # USB image import wizard
│ ├── unattend_editor.html # XML editor for unattend files
│ ├── startnet_editor.html # startnet.cmd WIM editor
│ ├── image_config.html # Per-image driver and hardware config
│ ├── enrollment.html # GCCH bulk enrollment packages
│ ├── backups.html # Clonezilla backup management
│ ├── reports.html # Blancco erasure reports
│ └── audit.html # Activity audit log
├── docs/
│ └── shopfloor-display-imaging-guide.md # End-user imaging guide
├── unattend/
│ └── FlatUnattendW10.xml # Windows unattend.xml template
├── boot-tools/ # Extracted boot tool files (gitignored)
@@ -157,8 +169,14 @@ pxe-server/
├── download-packages.sh # Downloads offline .debs + pip wheels
├── build-usb.sh # Builds the installer USB (2-partition)
├── prepare-boot-tools.sh # Extracts and patches boot tool files
├── build-proxmox-iso.sh # Builds self-contained Proxmox installer ISO
├── build-proxmox-iso.sh # Builds self-contained Proxmox installer ISO
├── test-vm.sh # KVM test environment for validation
├── test-lab.sh # Full PXE lab with server + client VMs
├── startnet-template.cmd # startnet.cmd template (synced with playbook copy)
├── Download-Drivers.ps1 # Download hardware drivers from GE CDN (Windows)
├── Upload-Image.ps1 # Upload MCL cache to PXE server via SMB (Windows)
├── download-drivers.py # Download Dell drivers directly from dell.com
├── sync_hardware_models.py # Sync hardware model configs across images
├── SETUP.md # Detailed setup guide
└── setup-guide-original.txt # Original manual setup notes (reference)
```
@@ -226,16 +244,14 @@ After the server is running, import deployment images via the web interface at `
| winpeapps | /srv/samba/winpeapps | WinPE deployment images |
| clonezilla | /srv/samba/clonezilla | Clonezilla disk backup images |
| blancco-reports | /srv/samba/blancco-reports| Blancco erasure reports (auto) |
| enrollment | /srv/samba/enrollment | GCCH bulk enrollment packages |
| image-upload | /home/pxe/image-upload | Image upload staging area |
All shares use guest access (no authentication) for ease of use on the isolated network.
## Blancco Drive Erasure
Blancco Drive Eraser is configured to automatically save XML erasure reports to the PXE server's Samba share (`blancco-reports`). The `prepare-boot-tools.sh` script patches Blancco's `config.img` to set:
- Network share hostname: `10.9.100.1`
- Share path: `blancco-reports`
- Auto-backup: enabled
- Erasure standard: NIST 800-88 Purge
Blancco Drive Eraser 7.15.1 boots via a native Ubuntu kernel with a custom initramfs (`blancco-init.sh`) that downloads and mounts the Blancco rootfs over HTTP. XML erasure reports are automatically saved to the PXE server's Samba share (`blancco-reports`). The server supports BMC cloud licensing for Blancco activation over WiFi.
Reports are viewable and downloadable from the web interface at `http://10.9.100.1:9009/reports`.
@@ -257,3 +273,11 @@ Reports are viewable and downloadable from the web interface at `http://10.9.100
| ef75839 | Auto-patch Blancco config.img for network report storage |
| 92c9b0f | Fix review findings: offline assets, security, audit logging |
| 725c8f4 | Change webapp to port 9009, add test VM script |
| f3a384f | Add Proxmox ISO builder, CSRF protection, boot-files integration |
| 1a5c4f7 | Eliminate USB requirement for WinPE PXE boot |
| dd2fec5 | Blancco PXE boot via Ubuntu kernel switch_root |
| 86660a0 | Remove UEFI HTTP Boot config from dnsmasq |
| 6d0e6ee | BIOS check fix, parallel downloads, shopfloor hardening |
| 7616549 | Shopfloor PC type system, webapp enhancements |
| b7cd097 | Blancco 7.15.1 upgrade: native kernel boot, BMC cloud licensing |
| 163e58a | Fix dnsmasq reboot cron: use /etc/cron.d/ instead of crontab |

View File

@@ -10,7 +10,7 @@ Client PXE boot
-> iPXE boot menu (HTTP, port 4433)
├── Windows PE -> wimboot -> boot.wim -> startnet.cmd -> Samba -> Image deployment
├── Clonezilla -> vmlinuz/initrd -> Disk cloning/imaging
├── Blancco -> vmlinuz/initrd -> NIST 800-88 drive erasure (auto-reports)
├── Blancco -> Native kernel + initramfs -> NIST 800-88 drive erasure (auto-reports)
└── Memtest86+ -> Memory diagnostics
```
@@ -117,6 +117,8 @@ Access at `http://10.9.100.1:9009` from any machine on the isolated network.
| startnet.cmd | /startnet | Edit startnet.cmd inside boot.wim (wimtools) |
| Clonezilla Backups| /backups | Upload/download/manage disk backup images |
| Blancco Reports | /reports | View/download drive erasure reports |
| Image Config | /images/*/config | Per-image driver, OS, and hardware config |
| Enrollment | /enrollment | GCCH bulk enrollment package management |
| Audit Log | /audit | Activity history for all write operations |
## Verification
@@ -159,12 +161,20 @@ pxe-server/
│ └── meta-data # Cloud-init metadata (required, empty)
├── playbook/
│ ├── pxe_server_setup.yml # Ansible: dnsmasq, Apache, Samba, iPXE, UFW, webapp
── inventory.ini # Ansible inventory
── inventory.ini # Ansible inventory
│ ├── startnet.cmd # WinPE startup script (injected into boot.wim)
│ ├── blancco-init.sh # Custom initramfs for Blancco PXE boot
│ ├── blancco-preferences.xml # Blancco auto-report preferences
│ ├── check-bios.cmd # Pre-imaging BIOS update checker
│ ├── FlatUnattendW10-shopfloor.xml # Shopfloor unattend.xml
│ └── shopfloor-setup/ # PC type setup scripts (Standard, CMM, Display, etc.)
├── webapp/
│ ├── app.py # Flask application
│ ├── app.py # Flask application (~1600 lines)
│ ├── requirements.txt # Python deps (flask, lxml)
│ ├── static/ # CSS, JS, fonts, logo (all bundled offline)
│ └── templates/ # Jinja2 HTML templates
│ └── templates/ # Jinja2 HTML templates (10 pages)
├── docs/
│ └── shopfloor-display-imaging-guide.md # End-user imaging guide
├── unattend/
│ └── FlatUnattendW10.xml # Windows unattend.xml template
├── boot-tools/ # Extracted boot files (gitignored, built by prepare-boot-tools.sh)
@@ -176,7 +186,14 @@ pxe-server/
├── download-packages.sh # Downloads all offline packages
├── build-usb.sh # Builds the 2-partition installer USB
├── prepare-boot-tools.sh # Extracts/patches boot tools from ISOs
├── build-proxmox-iso.sh # Builds self-contained Proxmox installer ISO
├── test-vm.sh # KVM test environment
├── test-lab.sh # Full PXE lab with server + client VMs
├── startnet-template.cmd # startnet.cmd template (synced with playbook copy)
├── Download-Drivers.ps1 # Download hardware drivers from GE CDN (Windows)
├── Upload-Image.ps1 # Upload MCL cache to PXE server via SMB (Windows)
├── download-drivers.py # Download Dell drivers directly from dell.com
├── sync_hardware_models.py # Sync hardware model configs across images
├── README.md # Project overview
└── setup-guide-original.txt # Original manual setup notes (reference)
```
@@ -208,5 +225,7 @@ pxe-server/
| winpeapps | /srv/samba/winpeapps | WinPE deployment images |
| clonezilla | /srv/samba/clonezilla | Clonezilla disk backup images |
| blancco-reports | /srv/samba/blancco-reports | Blancco erasure reports (auto)|
| enrollment | /srv/samba/enrollment | GCCH bulk enrollment packages |
| image-upload | /home/pxe/image-upload | Image upload staging area |
All shares use guest access for the isolated network.

View File

@@ -70,16 +70,21 @@ if ($pcType -ne "Shopfloor") {
Write-Host "Shopfloor setup complete for $pcType."
# Copy backup lockdown script to SupportUser desktop
# Copy utility scripts to SupportUser desktop
$lockdownScript = Join-Path $setupDir "backup_lockdown.bat"
if (Test-Path $lockdownScript) {
Copy-Item -Path $lockdownScript -Destination "C:\Users\SupportUser\Desktop\backup_lockdown.bat" -Force
Write-Host "backup_lockdown.bat copied to desktop."
}
$syncScript = Join-Path $setupDir "Shopfloor\sync_intune.bat"
if (Test-Path $syncScript) {
Copy-Item -Path $syncScript -Destination "C:\Users\SupportUser\Desktop\sync_intune.bat" -Force
Write-Host "sync_intune.bat copied to desktop."
}
# Set auto-logon to expire after 2 more logins
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoLogonCount /t REG_DWORD /d 2 /f | Out-Null
Write-Host "Auto-logon set to 2 remaining logins."
# Set auto-logon to expire after 1 more login
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoLogonCount /t REG_DWORD /d 1 /f | Out-Null
Write-Host "Auto-logon set to 1 remaining login."
Write-Host "Rebooting in 10 seconds..."
shutdown /r /t 10

View File

@@ -1,6 +1,36 @@
# 03-StartMenu.ps1 — Create Start Menu shortcuts for all users (baseline)
# Shortcuts in ProgramData\Microsoft\Windows\Start Menu\Programs\ persist for all accounts.
# --- Remove all default pinned Start Menu tiles ---
# Unpin tiles for the current user
try {
$shell = New-Object -ComObject Shell.Application
$shell.NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items() | ForEach-Object {
$_.Verbs() | Where-Object { $_.Name -match 'Unpin from Start|Un.*pin' } | ForEach-Object { $_.DoIt() }
}
Write-Host "Unpinned all default Start Menu tiles for current user."
} catch {
Write-Warning "Could not unpin Start tiles: $_"
}
# Set blank layout for future user profiles
$blankLayout = @"
<LayoutModificationTemplate xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout"
xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout"
Version="1" xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification">
<LayoutOptions StartTileGroupCellWidth="6" />
<DefaultLayoutOverride>
<StartLayoutCollection>
<defaultlayout:StartLayout GroupCellWidth="6" />
</StartLayoutCollection>
</DefaultLayoutOverride>
</LayoutModificationTemplate>
"@
$layoutDir = "C:\Users\Default\AppData\Local\Microsoft\Windows\Shell"
if (-not (Test-Path $layoutDir)) { New-Item -Path $layoutDir -ItemType Directory -Force | Out-Null }
$blankLayout | Out-File -FilePath "$layoutDir\LayoutModification.xml" -Encoding UTF8 -Force
Write-Host "Set blank Start Menu layout for future users."
$startMenu = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs"
$shell = New-Object -ComObject WScript.Shell

View File

@@ -0,0 +1,80 @@
@echo off
title Intune Policy Sync
:: Self-elevate to administrator
net session >nul 2>&1
if %errorlevel% neq 0 (
powershell -Command "Start-Process '%~f0' -Verb RunAs"
exit /b
)
echo.
echo ========================================
echo Intune Policy Sync
echo ========================================
echo.
:: Check current state
reg query "HKLM\Software\GE\SFLD" >nul 2>&1
if %errorlevel% equ 0 (
echo SFLD policies already applied.
echo.
echo Run sync anyway? (Y/N)
choice /c YN /n
if errorlevel 2 exit /b
)
:: Trigger sync via the MDM enrollment scheduled task
echo Triggering Intune sync...
powershell -ExecutionPolicy Bypass -Command ^
"$enrollPath = 'HKLM:\SOFTWARE\Microsoft\Enrollments'; "^
"$found = $false; "^
"Get-ChildItem $enrollPath -ErrorAction SilentlyContinue | ForEach-Object { "^
" $id = $_.PSChildName; "^
" $provider = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).ProviderID; "^
" if ($provider -eq 'MS DM Server') { "^
" $found = $true; "^
" Write-Host \"Enrollment ID: $id\"; "^
" $taskPath = \"\Microsoft\Windows\EnterpriseMgmt\$id\\\"; "^
" Get-ScheduledTask -TaskPath $taskPath -ErrorAction SilentlyContinue | "^
" Where-Object { $_.TaskName -match 'Schedule #3' } | "^
" ForEach-Object { "^
" Start-ScheduledTask -InputObject $_; "^
" Write-Host \"Sync triggered: $($_.TaskName)\"; "^
" }; "^
" } "^
"}; "^
"if (-not $found) { Write-Host 'ERROR: No Intune enrollment found.' -ForegroundColor Red }"
echo.
echo Waiting for SFLD group policies (HKLM\Software\GE\SFLD)...
echo Press Ctrl+C to stop waiting.
echo.
:: Poll every 15 seconds for up to 10 minutes
set /a attempts=0
set /a max=40
:poll
reg query "HKLM\Software\GE\SFLD" >nul 2>&1
if %errorlevel% equ 0 (
echo.
echo ========================================
echo SFLD group policies applied!
echo ========================================
echo.
pause
exit /b
)
set /a attempts+=1
if %attempts% geq %max% (
echo.
echo Timed out after 10 minutes. SFLD policies not yet applied.
echo The device category may not be assigned yet in Intune.
echo Assign the category in the portal, then run this again.
echo.
pause
exit /b
)
echo [%attempts%/%max%] Waiting... checking again in 15s
timeout /t 15 /nobreak >nul
goto poll