Domain Auto-Enrollment / Hostname Management with Powershell

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.)


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *