I am working on a project where I spin up a number of Windows servers into AWS and had to automate the AD enrollment and hostname setting. To do this, I used the following powershell script which I setup as a scheduled task to run at startup and then create an AMI and/or template from the instance.
This script could use some additional error checking and validation and is a work in progress.
# # Verify hostname and domain membership. # - Fix if not valid. # # # There are 4 possible states that this script accounts for: # # 1. Computer is a valid member of the domain with proper hostname. # 2. Computer is an invalid member of the domain. # 3. Computer is not a member of the domain. # 4. Computer has an invalid hostname. # # There are 4 possible scenarios that must be played out with relation to # the above states: # 1. Do nothing. # 2. Remove computer from domain and reboot (essentially places computer in state 3 on boot). # 3. Join the domain, reboot. # 4. Change hostname, reboot. # # Note that some machines may go through each of the 4 states before finishing configuration. # # # join domain values # $domain = "MYDOMAIN" $user = "MYDOMAIN\MYUSER" $pass = "MYSECRET" # # Function to set hostname to hexadecimal representation of IP address # to ensure unique hostname among environments. # function SetHexHostname { $hostName ; # Get IP Address of host $myIpAddress = "{0:x}" -f (Get-WmiObject Win32_NetworkAdapterConfiguration | ? { $_.IPAddress -ne $null}).ipaddress # split ip into 4 octets, prep to convert to hexadecimal $octets = $myIpAddress.split(".") foreach ($octet in $octets) { $hexOctet = [System.String]::Format("{0:X}",[System.Convert]::ToUInt32($octet)) # Prepend 0 to beginning if less than 2 digits if ( $hexOctet.Length -lt 2 ) { $hexOctet = "0" + "$hexOctet" } $hostName = "$hostName" + "$hexOctet" } $hostName = "IP-" + $hostName # # If the hostname does not match, change it. # if ( $hostName.CompareTo( $scriptHost ) -ne 0 ) { # # Must perform as domain member with privileges to update AD with new name # - or as local admin when not a member of domain? # $computerinfo = Get-WmiObject -Class Win32_ComputerSystem $computerinfo.Rename( $hostName ) } } $secpassword = ConvertTo-SecureString $pass -AsPlainText -Force $credentials = New-Object System.Management.Automation.PSCredential($user, $secpassword) # # hostname to operate against - typically this host # $scripthost = get-content env:computername # # Check this location for domain membership details. # $adminpath = Test-Path \\$scripthost\admin$ # # Is admin share available? # if ($adminpath -eq "TRUE") { $ObjReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $scripthost) $ObjRegKey = $ObjReg.OpenSubKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters") $DomName = $ObjRegKey.GetValue("Domain") # # If domain member of domain, validate membership # if ( $DomName -eq $domain ) { Write-Host "$scripthost is a member of $DomName" # # Validate domain membership # $job = Start-Job -Credential $credentials -ScriptBlock { Test-ComputerSecureChannel } Wait-Job $job | Out-Null $validDomainMember = Receive-Job $job Remove-Job $job if ( $validDomainMember ) { Write-Host "Valid domain member" # # After validating domain membership, change hostname. # # - This has an unfortunate side effect of not allowing the script to run any more due # to the job being scheduled as a local admin (with hostname). # SetHexHostname } else { write-host "Not a valid domain member" # # Leave domain by joing workgroup "workgroup" and restart. # Add-Computer -WorkGroupName "WorkGroup" -Credential $credentials Restart-Computer -ComputerName $scripthost } } else { write-host "Not part of domain, joining $domain" Add-Computer -DomainName $domain -Credential $credentials Restart-Computer -ComputerName $scripthost } } else { Write-Host "$scripthost: Computer not found or no access to admin share for me" }
(Note: does not work on 2003 R2 due to some winRM issues — if you know how to resolve this, please contact me.)
Leave a Reply