Archive for August, 2011

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

Wednesday, August 17th, 2011

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

Update ssh private key pass phrase.

Monday, August 15th, 2011

I like to keep certain pass words in sync with one another as I perform gigs for various clients and adhere to pass word policies for each company. As part of the password update, I typically need to update my SSH key pass phrase using the following command:

$ ssh-keygen -f ~/.ssh/id_rsa  -p

Note that the filename in question is my private key, specified by the -f.

That allows me to keep the same password across a single client or organization.