Migration ; Stage Two – Active Directory Cleanup

Why migrate unused service accounts, user objects and computer accounts from your source domains to the target? A migration is an ideal opportunity to cleanup all of the disused and legacy objects from your environment.

A simple way to achieve a user purge to is to query the lastLogonTimeStamp attribute on all user objects. This will immediately provide a reliable picture of recent account utilisation across the domain. The lastLogonTimeStamp attribute is new to Windows Server 2003, as opposed to the Windows 2000 lastLogon attribute which will vary on each Domain Controller within the domain, is replicated to all Domain Controllers.

The following vbScript will perform the query, creating a report on recent account usage:

Sub ListUsers( strDomain )
Set objComputer = GetObject(“WinNT://” & strNetBIOSDomain )
objComputer.Filter = Array( “User” )
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set objFile = fso.CreateTextFile(fileUserLst, True)
Dim strUserName, objUser, objLogon, intLogonTime

‘ Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

For Each objUser In objComputer
On Error Resume Next

‘ Specify the NT name of the user.
strNTName = objUser.Name

‘ Use the NameTranslate object to convert the NT user name to the
‘ Distinguished Name required for the LDAP provider.
Set objTrans = CreateObject(“NameTranslate”)

‘ Initialize NameTranslate by locating the Global Catalog.
objTrans.Init ADS_NAME_INITTYPE_GC, “”
‘ Use the Set method to specify the NT format of the object name.
objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain & “” & strNTName

‘ Use the Get method to retrieve the RPC 1779 Distinguished Name.
strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)

‘ Bind to the user object in Active Directory with the LDAP provider.
Set objUser = GetObject(“LDAP://” & strUserDN)

‘MsgBox(“DN = ” & strUserDN)
‘ This code prints the last logon timestamp for a user.
set objLogon = objUser.Get(“lastLogonTimestamp”)
intLogonTime = objLogon.HighPart * (2^32) + objLogon.LowPart
intLogonTime = intLogonTime / (60 * 10000000)
intLogonTime = intLogonTime / 1440

‘…and writes to file specified by user
objFile.WriteLine( objUser.Name & “;” & intLogonTime + #1/1/1601#)

Next
End Sub
‘****************************************************************************
‘ Main
‘ ****************************************************************************
Do
  strNetBIOSDomain = inputbox(“Please enter the NetBios domainname. example; mydomain”, “NetBIOS domain name” )
  fileUserLst = inputbox(“Please enter a file name and path for the output file.”, “File path”, “C:” & strNetBIOSDomain & ” users.csv”)
Loop until strNetBIOSDomain “”

ListUsers( strDomain )

With regards to computer accounts, don’t worry too much about the cleanup of these objects as you will be migrating all of the active computer objects within your environment individually duringthe migration process. Therefore what is left is likely to be the disused / legacy objects.

I would also suggest reviewing security group memberships and useage. This can be achieved by looking at logon scripts for any group based functions, group policy assignment and file share permission auditing. DSQUESRY can be used to return these values for each group individually:

dsquery * “” -attr name createTimestamp modifyTimestamp

Or for all security groups (well all objects in the case of this command) in an OU:

dsquery * “OU=Security Groups,DC=Domain,DC=local” -attr name modifyTimeStamp

This helps to further justify normalising your OU structure prior to the migration process (see here.) Without normalisation of the Security Gorups into a particlar OU it would be more complex to return the required information.

Perform the same steps with your Distribution Lists to ensure you’re not wasting time an effort migrating objects which are no longer in use.

Finally, if you are using the Quest tools identify which customAttributes are in use within your environment.These attributes are essential during the migration and each source pair will require 2 free sttributes for the duration of the migration.