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