Archive for July, 2011

Domain Auto-Enrollment / Hostname Management with Powershell

Tuesday, July 26th, 2011

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

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

Fedora 15 Automatic Updates

Friday, July 15th, 2011

Now why would a Linux distribution have automatic updates? They don’t. They never have. They allow the user to maintain software updates without intervention. Automation is performed by the administrator and that’s why most folks use Linux.

Not any more.

I was tailing the system log on my Fedora 15 desktop yesterday when I see this message roll across the display:

Jul 14 16:32:14 my-desktop dbus-daemon: [system] Activating service name='org.freedesktop.PackageKit' (using servicehelper)
Jul 14 16:32:14 my-desktop dbus-daemon: [system] Successfully activated service 'org.freedesktop.PackageKit'
Jul 14 16:33:53 my-desktop yum[18560]: Updated: 32:bind-license-9.8.0-7.P4.fc15.noarch
Jul 14 16:33:55 my-desktop yum[18560]: Updated: 32:bind-libs-9.8.0-7.P4.fc15.i686
Jul 14 16:33:59 my-desktop yum[18560]: Updated: 32:bind-utils-9.8.0-7.P4.fc15.i686
Jul 14 16:34:01 my-desktop yum[18560]: Updated: 32:bind-libs-lite-9.8.0-7.P4.fc15.i686
Jul 14 16:34:03 my-desktop yum[18560]: Updated: kernel-headers-
Jul 14 16:34:15 my-desktop yum[18560]: Installed: kernel-devel-
Jul 14 16:34:28 my-desktop yum[18560]: Installed: kernel-

Now I’m no fan of PackageKit. I dislike the new era of deveopers who have come in and name their daemons, packages, and config files in camel case going against the long running standard of using all lower case. This is especially true of anything with a Kit appended to the name. This is the same movement that is trying to take the desktop with Linux and destroying the simple nature of a beautiful system.

Now, here is how you disable the automatic updates:
1. Install or confirm that you have gnome-packagekit installed.
2. Run ‘gpk-prefs’ and configure it to never check for any updates.

Jenkins Slave Authentication

Friday, July 8th, 2011

Note that the following applies to a Windows Slave connecting to a Linux master.

When implementing authentication with Jenkins and using slaves, it is important to allow slaves to authenticate to the master in order to continue working. When using the JNLP protocol with slaves, the following may be done to authenticate slaves to the master:

1. Edit the jenkins-slave.xml to reflect the following arguments — append to the end:

-classpath "%BASE%\lib\commons-codec-1.5.jar" -jnlpCredentials username:password -noCertificateCheck

Once that is complete, download the common-codec-1.5.jar and place in the lib directory within the jenkins slave working directory (you will have to create this if it does not yet exist).

Download from:

Next, restart the Jenkins Slave service on the slave and verify.