diff --git a/README.md b/README.md index 1e66605..8a141c7 100644 --- a/README.md +++ b/README.md @@ -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 | diff --git a/SETUP.md b/SETUP.md index 2bdf53b..bba0bcf 100644 --- a/SETUP.md +++ b/SETUP.md @@ -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. diff --git a/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 b/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 index 7574579..fd4191e 100644 --- a/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 +++ b/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 @@ -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 diff --git a/playbook/shopfloor-setup/Shopfloor/03-StartMenu.ps1 b/playbook/shopfloor-setup/Shopfloor/03-StartMenu.ps1 index 5ad476f..8e37ef4 100644 --- a/playbook/shopfloor-setup/Shopfloor/03-StartMenu.ps1 +++ b/playbook/shopfloor-setup/Shopfloor/03-StartMenu.ps1 @@ -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 = @" + + + + + + + + +"@ +$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 diff --git a/playbook/shopfloor-setup/Shopfloor/sync_intune.bat b/playbook/shopfloor-setup/Shopfloor/sync_intune.bat new file mode 100644 index 0000000..d848fb8 --- /dev/null +++ b/playbook/shopfloor-setup/Shopfloor/sync_intune.bat @@ -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