Domain Auto-Enrollment / Hostname Management with Powershell (v2)

I am realizing now that I need to get a git repo setup that is publicly accessible which will allow me to share scripts and other code snippets that I’m working on.

Here is the second iteration of the powershell domain/hostname management script that I’m working on. It will also update the SQL Server dbname to reflect the hostname change on SQL Server 2008 boxes.

# This script will re-initialize domain membership and change the hostname to reflect the
# hexadecimal representation of the IP address assigned on boot.
#
# Author:  Josh Miller
# Date:    8/12/2011
#
# Note that there are 4 possible conditions that a host may come up in:
# 1. valid domain, invalid hostname
#    (although domain membership is invalid)
# 2. invalid domain, invalid hostname
# 3. invalid domain, valid hostname
# 4. valid domain, valid hostname
#
# The actions that will be taken for each of these conditons are:
# 1. leave domain, reboot
# 2. change hostname, reboot
# 3. join domain, reboot
# 4. do nothing, final condition
#
# Setup:
# 1. setup scheduled task to run on start-up as local administrator
# 2. create bat file to execute this powershell script, ie:
#   powershell -command "& 'c:\tools\powershell\domain.ps1' "
# 3. create AMI/template on network with DHCP
# 4. join to domain
# 5. verify that scheduled task is running as local administrator, bear
#    in mind that hostnames change frequently and just before you clone/
#    create the AMI, set the credentials again.
#
# Note:  this should really not work.  Once the hostname changes and the
#        machine reboots, it should not have permission to run one more
#        time to join the domain.  I don't understand why it works.  The
#        next run fails due to lack of permissions which is understandable
#        and acceptable.
#

# join domain values
$domain = "domain.com"
$user   = "domain\ad_user"
$pass   = "mysecret"

$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

# Leave the domain.
function LeaveDomain {

  Add-Computer -WorkGroupName "WorkGroup" -Credential $credentials

}

# Join the domain.
function JoinDomain {

  Add-Computer -DomainName $domain -Credential $credentials

}

# Restart the machine
function RestartMachine {

  Restart-Computer -Force

}

# Function to set hostname to hexadecimal representation of IP address
function SetHexHostname ([string] $setHostName) {

  # Return value of 5    means 'Access denied'.
  # Return value of 1326 means 'Logon failure: unknown username or bad password'.

  $computerinfo = Get-WmiObject -Class Win32_ComputerSystem
  $computerinfo.Rename( $setHostName )

}

# Function to get hostname as hexadecimal representation of IP address
function GetHexHostname {

  $getHostName = "" ;

  # 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"
    }

    $getHostName = "$getHostName" + "$hexOctet"
  }

  $getHostName = "IP-" +  $getHostName

  Return $getHostName

}

# Function updates the dbname with hostname - always assumes needs changed.
function SetDBName ([string] $setDBName) {

  # Get SQL server version
  #  8.x = 2000
  #  9.x = 2005
  # 10.x = 2008
  $server_version = Invoke-Sqlcmd -Query "Select serverproperty('productversion') as version;"
  $sql_version    = $server_version.version

  if ( $sql_version -lt 9 ) {

    # works for sql2000
    $results = Invoke-Sqlcmd -Query "select srvname from sysservers;"
    $current_dbname = $results.srvname

  } else {

    # works for sql2005/2008
    $results = Invoke-Sqlcmd -Query "select name from sys.servers;"
    $current_dbname = $results.name

  }

  if ( $setDBName.CompareTo($current_dbname) -ne 0 ) {

    Write-Host "Updating DBName to match hostname"

    $drop_dbname = Invoke-Sqlcmd -Query "exec sp_dropserver '$current_dbname';"
    $add_dbname  = Invoke-Sqlcmd -Query "exec sp_addserver  '$setDBName', local;"

  }

}

#                                       #
# Start program execution.  #
#                                       #

# Ensure hostname is properly set
$testHostname = GetHexHostname

# Is admin share available?
if ( ! ( Test-Path \\$scripthost\admin$ ) -eq "TRUE") {
  Write-Host "Unable to access admin share."
  exit
}

$ObjReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $scripthost)
$ObjRegKey = $ObjReg.OpenSubKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters")
$DomName = $ObjRegKey.GetValue("Domain")

if ( $DomName -eq $domain ) {

  Write-Host "Valid domain."

  if ( $testHostName.CompareTo( $scripthost ) -ne 0 ) {

    Write-Host "Invalid hostname, leaving domain."

    LeaveDomain
    RestartMachine

  } else {

    Write-Host "Valid domain and hostname."

  }

} else {

  Write-Host "Invalid domain."

  if ( $testHostName.CompareTo( $scripthost ) -ne 0 ) {

    Write-Host "Hostname not set correctly, setting to $testHostName"
    SetHexHostname ( $testHostname )
    SetDBName ( $testHostname )

  } else {

    Write-Host "Valid hostname, joining domain."
    JoinDomain

  }

  # Restart after either changing hostname or joining domain.
  RestartMachine

}

As always, let me know if you have any improvements, bugs, suggestions, etc.. at:
linux (at) itsecureadmin (dot) com


Posted

in

,

by

Tags:

Comments

Leave a Reply

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