#Requires -RunAsAdministrator <# .SYNOPSIS Phase 3.1: Domain join a workstation. .DESCRIPTION Documents current state, creates local admin backup, verifies DNS, and joins the machine to cascades.local domain. Run on each target workstation via ScreenConnect. .NOTES Order: DESKTOP-KQSL232 -> CHEF-PC -> SALES4-PC -> MDIRECTOR-PC Machine will REBOOT after domain join. #> param( [string]$LocalAdminPassword = "" ) $DomainName = "cascades.local" $OUPath = "OU=Staff PCs,OU=Workstations,DC=cascades,DC=local" $MigrationDir = "C:\IT-Migration" Write-Host "=== Phase 3.1: Domain Join - $env:COMPUTERNAME ===" -ForegroundColor Cyan Write-Host "" # --- Step 1: Document current state --- Write-Host "--- Step 1: Documenting current state ---" -ForegroundColor Yellow New-Item -Path $MigrationDir -ItemType Directory -Force | Out-Null $infoFile = "$MigrationDir\pre-join-info_$(Get-Date -Format 'yyyy-MM-dd_HHmm').txt" "=== Pre-Join State for $env:COMPUTERNAME ===" | Out-File $infoFile "Timestamp: $(Get-Date)" | Out-File $infoFile -Append "" | Out-File $infoFile -Append "--- SYSTEM INFO ---" | Out-File $infoFile -Append systeminfo | Out-File $infoFile -Append "--- IP CONFIG ---" | Out-File $infoFile -Append ipconfig /all | Out-File $infoFile -Append "--- PRINTERS ---" | Out-File $infoFile -Append Get-Printer -ErrorAction SilentlyContinue | Format-List | Out-File $infoFile -Append "--- MAPPED DRIVES ---" | Out-File $infoFile -Append net use | Out-File $infoFile -Append "--- LOCAL USERS ---" | Out-File $infoFile -Append Get-LocalUser | Format-Table | Out-File $infoFile -Append "--- INSTALLED SOFTWARE ---" | Out-File $infoFile -Append Get-WmiObject Win32_Product | Select-Object Name, Version | Sort-Object Name | Format-Table | Out-File $infoFile -Append Write-Host " [OK] State documented at $infoFile" -ForegroundColor Green # --- Step 2: Create local admin backup --- Write-Host "`n--- Step 2: Creating MSPAdmin local account ---" -ForegroundColor Yellow $localAdmin = Get-LocalUser -Name "Localadmin" -ErrorAction SilentlyContinue if (-not $localAdmin) { if (-not $LocalAdminPassword) { Write-Host " [INPUT NEEDED] Enter password for Localadmin account:" -ForegroundColor Yellow $securePassword = Read-Host -AsSecureString } else { $securePassword = ConvertTo-SecureString $LocalAdminPassword -AsPlainText -Force } New-LocalUser -Name "Localadmin" -Password $securePassword -PasswordNeverExpires -AccountNeverExpires -Description "Local emergency admin - migration rollback" | Out-Null Add-LocalGroupMember -Group "Administrators" -Member "Localadmin" | Out-Null Write-Host " [OK] Localadmin local admin created" -ForegroundColor Green } else { Write-Host " [SKIP] Localadmin already exists" -ForegroundColor DarkGray } # --- Step 3: Verify DNS --- Write-Host "`n--- Step 3: Verifying DNS resolution ---" -ForegroundColor Yellow try { $dns = Resolve-DnsName "cs-server.cascades.local" -ErrorAction Stop Write-Host " [OK] cs-server.cascades.local resolves to: $($dns.IPAddress -join ', ')" -ForegroundColor Green } catch { Write-Host " [FAIL] Cannot resolve cs-server.cascades.local" -ForegroundColor Red $currentDns = (Get-DnsClientServerAddress -AddressFamily IPv4 | Where-Object { $_.ServerAddresses.Count -gt 0 }) Write-Host " Current DNS servers:" -ForegroundColor Yellow foreach ($adapter in $currentDns) { Write-Host " $($adapter.InterfaceAlias): $($adapter.ServerAddresses -join ', ')" -ForegroundColor Yellow } Write-Host "" Write-Host " Options:" -ForegroundColor Cyan Write-Host " [F] Fix DNS — set primary DNS to 192.168.2.254 (CS-SERVER) and retry" -ForegroundColor Cyan Write-Host " [A] Abort — exit and fix manually" -ForegroundColor Cyan $choice = Read-Host " Enter F or A" if ($choice -eq 'F') { # Get the active adapter (the one with a default gateway) $activeAdapter = Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null } | Select-Object -First 1 if (-not $activeAdapter) { Write-Host " [FAIL] No active adapter with a gateway found. Fix manually." -ForegroundColor Red exit 1 } $ifIndex = $activeAdapter.InterfaceIndex $ifName = $activeAdapter.InterfaceAlias Write-Host " Setting DNS on '$ifName' to 192.168.2.254 (CS-SERVER)..." -ForegroundColor Yellow Set-DnsClientServerAddress -InterfaceIndex $ifIndex -ServerAddresses @('192.168.2.254') Clear-DnsClientCache # Retry resolution Start-Sleep -Seconds 2 try { $dns = Resolve-DnsName "cs-server.cascades.local" -ErrorAction Stop Write-Host " [OK] DNS fixed. cs-server.cascades.local resolves to: $($dns.IPAddress -join ', ')" -ForegroundColor Green } catch { Write-Host " [FAIL] Still cannot resolve after DNS change. Check network connectivity to 192.168.2.254" -ForegroundColor Red exit 1 } } else { Write-Host " [ABORT] Fix DNS and re-run the script." -ForegroundColor Yellow exit 1 } } # --- Step 4: Confirm and join --- Write-Host "`n--- Step 4: Domain Join ---" -ForegroundColor Yellow Write-Host " Computer: $env:COMPUTERNAME" -ForegroundColor Cyan Write-Host " Domain: $DomainName" -ForegroundColor Cyan Write-Host " OU: $OUPath" -ForegroundColor Cyan Write-Host "" Write-Host " Machine will REBOOT after joining." -ForegroundColor Yellow Write-Host "" $confirm = Read-Host " Type 'JOIN' to proceed (anything else to abort)" if ($confirm -ne "JOIN") { Write-Host " [ABORT] Domain join cancelled by user" -ForegroundColor Yellow exit 0 } try { Write-Host " Enter domain admin credentials..." -ForegroundColor Yellow Add-Computer -DomainName $DomainName -OUPath $OUPath -Credential (Get-Credential) -Restart -Force Write-Host " [OK] Domain join initiated - machine is restarting..." -ForegroundColor Green } catch { Write-Host " [ERROR] Domain join failed: $_" -ForegroundColor Red Write-Host " Troubleshooting:" -ForegroundColor Yellow Write-Host " - Verify credentials (domain admin)" -ForegroundColor Yellow Write-Host " - Check firewall rules allow AD ports from this subnet" -ForegroundColor Yellow Write-Host " - Run phase3-pre-join-verify.ps1 for diagnostics" -ForegroundColor Yellow exit 1 }