Thursday, February 23, 2012

Crazy uptime (windows 2000 domain controller)

C:\>uptime
\\SRVNAMECHANGED has been up for: 2111 day(s), 10 hour(s), 31 minute(s), 52 second(s)

Anyone got a datacenter and server that stable?  This is a Dell PE2650 with windows 2000, which also has 0 hardware problems. 

Tuesday, February 21, 2012

Converting guid to escaped bytes for LDAP lookups (powershell, AD ACL)

If you have looked at access lists in active directory using get-acl, you may be familiar with this type of entry

ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : None
ObjectType : bf967aa8-0de6-11d0-a285-00aa003049e2
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : S-1-5-32-550
IsInherited : False
InheritanceFlags : None
PropagationFlags : None

Given that the ObjectType and occsionally the InheritedObjectType are guid's, it may be difficult to determine what this entry is referring to. You can do an ldap lookup into the schema partition to find what object or attribute this guid is referring to, however the ldap filter for the search needs the guid in binary. .Net comes to the rescue for easy conversion to binary, but this is not sufficient for an ldap search, as it returns a byte array.

You can create a GUID object in powershell by casting $myguid = [guid]"bf967aa8-0de6-11d0-a285-00aa003049e2"

In this object, there is a byte conversion method tobytearray().

For ldap searches, we need the byte array escaped with forward slashes on each byte. To do this you can run the guid through this simple function


function guid-toescapedbyte($guid) {
     $bytearr = $guid.tobytearray()
     $bytestr = ""
     foreach ($byte in $bytearr) {
          $str = "\" + "{0:x}" -f $byte
          $bytestr += $str
     }
     return $bytestr
}

In our example we will get this:

guid-toescapedbyte([guid]"bf967aa8-0de6-11d0-a285-00aa003049e2")
\a8\7a\96\bf\e6\d\d0\11\a2\85\0\aa\0\30\49\e2

We can add this to a filter like this:

$de = new-object directoryservices.directoryentry("LDAP://cn=schema,cn=configuration,dc=contoso,dc=com")
$ds = new-object directoryservices.directorysearcher($de)
$bytestr =  guid-toescapedbyte [guid]"bf967aa8-0de6-11d0-a285-00aa003049e2"
$ds.filter = "(|(schemaidguid=$bytestr)(attributesecurityguid=$bytestr))"

$ds.findone().properties

Name Value
---- -----
systemmustcontain {versionNumber, uNCName, shortServerName, ser...
admindisplayname {Print-Queue}
name {Print-Queue}
objectguid {184 69 64 30 219 21 163 78 168 107 59 106 18...
systemonly {False}
whencreated {10/21/1630 4:21:11 PM}
defaultobjectcategory {CN=Print-Queue,CN=Schema,CN=Configuration,DC...
systemflags {16}
ldapdisplayname {printQueue}
usnchanged {4748}
objectcategory {CN=Class-Schema,CN=Schema,CN=Configuration,D...
systemposssuperiors {organizationalUnit, domainDNS, container, co...
showinadvancedviewonly {True}
defaultsecuritydescriptor {D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RP...
instancetype {4}
distinguishedname {CN=Print-Queue,CN=Schema,CN=Configuration,DC...
cn {Print-Queue}
dscorepropagationdata {1/1/1601 12:00:00 AM}
objectclass {top, classSchema}
defaulthidingvalue {False}
usncreated {4748}
rdnattid {cn}
objectclasscategory {1}
systemmaycontain {priority, printStatus, printStartTime, print...
schemaidguid {168 122 150 191 230 13 208 17 162 133 0 170 ...
subclassof {connectionPoint}
whenchanged {6/11/2010 5:23:32 PM}
governsid {1.2.840.113556.1.5.23}
admindescription {Print-Queue}
adspath {LDAP://CN=Print-Queue,CN=Schema,CN=Configura...


And we can see from our results that our ACL is related to print queue child objects. If we translate the SID, we will see this is the print operators builtin group.

Wednesday, February 1, 2012

Dell components check for updates via powershell (remote machine SUU)

Yesterday I posted on my XPath learning that I was going through while playing around with the Dell SUU catalog.xml file.  After further coding today, I threw together a good functional prototype of a powershell script to run SUU checks on remote machine.  It will find the upgradable components for the target machine, and return details like this:

Component      : FlashBIOS Updates
path           : PE2850_BIOS_WIN_A07.EXE
vendorVersion  : A07
currentversion : A05
releaseDate    : May 23, 2008
Criticality    : Optional
AtCurrent      : False

Component      : Embedded Server Management
path           : BMC_FRMW_WIN_R223079.EXE
vendorVersion  : 1.83
currentversion : 1.52
releaseDate    : June 30, 2009
Criticality    : Optional
AtCurrent      : False

for all firmware, bios, and drivers (probably OMSA too).  The AtCurrent value is a true/false test to show if you are at the current level (current to your version of SUU that you are using).  The script takes a server name and path (to your catalog.xml file in the suu\repository folder), and remotely checks the machine.  This works for windows machines only, since it uses WMI.  I'm sure some method of scripting using omreport data could be used to due similiar work for Linux.  Some ideas for using this information for updating, take the file name returned in each component, copy the file from the repository to the remote machine and run the installs with the silent run switch.



#Requires -version 2
#Author: Nathan Linley
#Script: Computer-DellUpdates
#Date: 2/9/2012

param(
 [parameter(mandatory=$true)][ValidateScript({test-path $_ -pathtype 'leaf'})][string]$catalogpath,
 [parameter(mandatory=$true,ValueFromPipeline=$true)][string]$server
)

function changedatacase([string]$str) {
 #we need to change things like this:  subDeviceID="1f17" to subDeviceID="1F17"
 #without changing case of the portion before the =
 if ($str -match "`=`"") {
  $myparts = $str.split("=")
  $result = $myparts[0] + "=" + $myparts[1].toupper()
  return $result
 } else { return $str}
}

$catalog = [xml](get-Content $catalogpath)
$oscodeid = &{
 $caption = (Get-WmiObject win32_operatingsystem -ComputerName $server).caption
 if ($caption -match "2003") {
  if ($caption -match "x64") { "WX64E" } else { "WNET2"}
 } elseif ($caption -match "2008 R2") { 
  "W8R2" 
 } elseif ($caption -match "2008" ) {
   if ($caption -match "x64") { 
    "WSSP2" 
   } else {
    "LHS86"
   } 
 }
}
write-debug $oscodeid

$systemID = (Get-WmiObject -Namespace "root\cimv2\dell" -query "Select Systemid from Dell_CMInventory" -ComputerName $server).systemid
$model = (Get-WmiObject -Namespace "root\cimv2\dell" -query "select Model from Dell_chassis" -ComputerName $server).Model
$model = $model.replace("PowerEdge","PE").replace("PowerVault","PV").split(" ")   #model[0] = Brand Prefix  #model[1] = Model #

$devices = Get-WmiObject -Namespace "root\cimv2\dell" -Class dell_cmdeviceapplication -ComputerName $server
foreach ($dev in $devices) {
 $xpathstr = $parts = $version = ""
 if ($dev.Dependent -match "(version=`")([A-Z\d.-]+)`"") { $version = $matches[2] } else { $version = "unknown" }
 $parts = $dev.Antecedent.split(",")
 for ($i = 2; $i -lt 6; $i++) {
  $parts[$i] = &changedatacase $parts[$i]
 }
 $depparts = $dev.dependent.split(",")
 $componentType = $depparts[0].substring($depparts[0].indexof('"'))
 Write-Debug $parts[1]
 if ($dev.Antecedent -match 'componentID=""') {
  $xpathstr = "//SoftwareComponent[@packageType='LWXP']/SupportedDevices/Device/PCIInfo"
  if ($componentType -match "DRVR") {
   $xpathstr += "[@" + $parts[2] + " and @" + $parts[3] + "]/../../.."
   $xpathstr += "/SupportedOperatingSystems/OperatingSystem[@osVendor=`'Microsoft`' and @osCode=`'" + $osCodeID + "`']/../.."
  } else {
   $xpathstr += "[@" + $parts[2] + " and @" + $parts[3] + " and @" + $parts[4] + " and @" + $parts[5] + "]/../../.."
   #$xpathstr += "/SupportedSystems/Brand[@prefix=`'" + $model[0] + "`']/Model[@systemID=`'" + $systemID + "`']/../../.."
   $xpathstr += "/ComponentType[@value='FRMW']/.."
   
  }
  $xpathstr += "/ComponentType[@value=" + $componentType + "]/.."
 } else {
  $xpathstr = "//SoftwareComponent[@packageType='LWXP']/SupportedDevices/Device[@" 
  $xpathstr += $parts[0].substring($parts[0].indexof("componentID"))
  $xpathstr += "]/../../SupportedSystems/Brand[@prefix=`'" + $model[0] + "`']/Model[@systemID=`'"
  $xpathstr += $systemID + "`']/../../.."
 }
 Write-Debug $xpathstr
 
 $result = Select-Xml $catalog -XPath $xpathstr |Select-Object -ExpandProperty Node
 $result |Select-Object @{Name="Component";Expression = {$_.category.display."#cdata-section"}},path,vendorversion,@{Name="currentversion"; Expression = {$version}},releasedate,@{Name="Criticality"; Expression={($_.Criticality.display."#cdata-section").substring(0,$_.Criticality.display."#cdata-section".indexof("-"))}},@{Name="AtCurrent";Expression = {$_.vendorVersion -le $version}}
}