#Requires -RunAsAdministrator param( [Parameter(Mandatory=$true)] [string]$Domain, [Parameter(Mandatory=$false)] [string]$ComputerName ) $ErrorActionPreference = "Stop" # Verify running as Administrator $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = [Security.Principal.WindowsPrincipal]$identity if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Error "This script must be run as a machine Administrator." exit 1 } # Verify Nebula service is running $nebulaSvc = Get-Service -Name "nebula" -ErrorAction SilentlyContinue if (-not $nebulaSvc -or $nebulaSvc.Status -ne "Running") { Write-Error "Nebula service is not running. Run install-nebula.ps1 first." exit 1 } # Validate computer name if provided if ($ComputerName) { if ($ComputerName.Length -gt 15) { Write-Error "Computer name '$ComputerName' exceeds 15 character limit." exit 1 } if ($ComputerName -notmatch '^[a-zA-Z0-9-]+$') { Write-Error "Computer name '$ComputerName' contains invalid characters. Use only letters, numbers, and hyphens." exit 1 } } # Check if already joined to this domain $cs = Get-WmiObject Win32_ComputerSystem $alreadyJoined = $cs.PartOfDomain -and $cs.Domain -eq $Domain if ($alreadyJoined) { Write-Host "This machine is already joined to '$Domain'. No changes needed." exit 0 } # Verify DNS can resolve the domain (i.e. DC is reachable) try { $resolved = Resolve-DnsName $Domain -ErrorAction Stop Write-Host "Resolved $Domain to $($resolved[0].IPAddress)" } catch { Write-Error "Cannot resolve domain '$Domain'. Ensure DNS is pointed at the domain controller (run set-dns.ps1 first)." exit 1 } # Prompt for domain credentials Write-Host "Enter credentials for a domain account with permission to join machines to '$Domain':" $credential = Get-Credential -Message "Domain join credentials for $Domain" if (-not $credential) { Write-Error "No credentials provided." exit 1 } # Warn if computer name doesn't match expected name if ($ComputerName -and $env:COMPUTERNAME -ne $ComputerName.ToUpper()) { Write-Warning "Current computer name '$env:COMPUTERNAME' does not match '$ComputerName'." Write-Warning "If you have a pre-staged AD object for '$ComputerName', rename this machine first and reboot before running this script." Write-Warning "Proceeding with domain join as '$env:COMPUTERNAME'..." } # Join the domain under the machine's current name Write-Host "Joining '$Domain' as '$env:COMPUTERNAME'..." try { Add-Computer -DomainName $Domain -Credential $credential -Force } catch { Write-Error "Failed to join domain: $_" exit 1 } # Verify the join succeeded $cs = Get-WmiObject Win32_ComputerSystem if ($cs.PartOfDomain -and $cs.Domain -eq $Domain) { Write-Host "Successfully joined '$Domain' as '$env:COMPUTERNAME'." Write-Host "" Write-Host "A restart is required for changes to take effect." $restart = Read-Host "Restart now? (y/n)" if ($restart -eq "y") { Restart-Computer -Force } } else { Write-Error "Domain join could not be verified." exit 1 }