A Directory Services Geek’s View on Active Directory Recovery in Windows Server 2008







Ulf B. Simon-Weidner
Ulf B. Simon-Weidner
 




Presented at



  • Microsoft TechEd:IT-Forum, Nov 2007, Barcelona, Spain

  • Microsoft Launch 2008, Feb. 2008, Frankfurt, Germany

  • Directory Experts Conference 2008, Chicago, USA

  • Microsoft TechEd IT-Pro, June 2008, Orlando, USA

In my session “A Directory Services Geek’s View on Active Directory-Restore in Windows Server 2008” I’m using a script to convert a LDIF-File from the changetype “Add” to changetype “modify”. Why is that?


I’ve presented on how to restore a Tombstone to a user-object with only a limited set of properties. Then I used Active Directory-Snapshots to dump a LDIF-File with all attributes of the recovered objects by running the LDIF-Export against the port where I provided the Snapshot:





ldifde.exe -r “(cn=Joe Doe)” -t 10000 -f joe.ldf
            ^                 ^        ^
Filter Snapshot-Port Output-Filename

Afterward we have a LDIF-File, however it is the changetype “Add”, which we could use to create a new user, but only if all attributes are writeable and the syntax is correct. However since we dumped all attributes there are some which even a domain admin is unable to write because they are owned by the system or because of other reasons. But I prefer to dump all of them if I need to fully restore a user, so I even get custom schema extensions and everything else which I might not think of if I use a manual list of attributes. Now we are challenged to modify a user which already exists, and to do this we can not use the default output of LDIFDE. We need to convert the file as illustrated in the following picture:


 BLD07


To do this I wrote the following script:


‘ ModifyLDIF
‘ Converts LDF-Files from Changetype ADD to Changetype MODIFY,
‘ in result every Attribute will be changed separately
‘ Import the file using ldifde -i -z -k -f filename.ldf to
‘ continue changing attributes if one is ‘unwriteable’
‘ Parameter: 
‘   sInput:  Path/File of the Inputfile (LDF)
‘   sOutput: Path/File of the Outputfile (LDF)
‘   bDelSource: wenn TRUE wird die Eingabedatei hinterher gelöscht
‘ (c) Ulf B. Simon-Weidner, www.msmvps.com/ulfbsimonweidner
 
set objArgs = WScript.Arguments
if objArgs.Count = 0 or objArgs.Count > 3 then ShowUsage
sInput = objArgs(0)
if objArgs.Count > 1 then
  sOutput = objArgs(1)
else
  sOutput = “”
  arrOut = split(sInput,“\”)
  for i = 0 to ubound(arrOut)-1
    sOutput = sOutput & arrOut(i) & “\”
    WScript.Echo sOutput
  next
  sOutput = sOutput & “mod_” & arrOut(ubound(arrOut))
  WScript.Echo sOutput
end if
if objArgs.Count > 2 then
  bDelSource = objArgs(2)
else
  bDelSource = FALSE
end if
WScript.Echo
WScript.Echo “ModifyLDIF.vbs”
WScript.Echo “(c) Ulf B. Simon-Weidner, www.msmvps.com/ulfbsimonweidner”
WScript.Echo
WScript.Echo “Inputfile:  “ & sInput
WScript.Echo “Outputfile: “ & sOutput
if bDelSource then WScript.Echo “Inputfile will be deleted after conversion”
WScript.Echo
ModifyLDIF sInput, sOutput, bDelSource
WScript.Quit
 
sub ModifyLDIF(sInput,sOutput,bDelSource)
  Set oFSO = CreateObject(“Scripting.FileSystemObject”)
  Set oInput = oFSO.OpenTextFile(sInput, 1)
  set oOutPut = oFSO.OpenTextFile(sOutput, 2, True)
  Do While oInput.AtEndOfStream <> True
    sLine = oInput.ReadLine
    if sLine<>“” then
      select case left(sLine,1)
        case ” “  
                  oOutput.WriteLine sLine
        case “-“
                  oOutput.WriteLine sLine
        case else
                  if bolBinary then
                    oOutput.WriteLine “-“
                    oOutput.WriteLine “”
                    bolBinary = FALSE
                  end if
                  sParm = left(sLine,instr(sLine,“:”)-1)
                  sValue = trim(mid(sLine,instr(sLine,“:”)+1))
                  if left(sValue,1) = “:” then
                    ‘First line of a binary value
                    oOutput.WriteLine “dn: “ & sCurrentDN
                    oOutput.WriteLine “changetype: modify”
                    oOutput.WriteLine “replace: “ & sParm
                    oOutput.WriteLine sParm & “:” & sValue
                    bolBinary = TRUE
                  else
                    select case sParm
                      case “dn”
                                sCurrentDN = sValue
                      case “changetype”
                                ‘ ignore this one
                      case “-“
                                ‘ ignore this one as well
                      case else
                                oOutput.WriteLine “dn: “ & sCurrentDN
                                oOutput.WriteLine “changetype: modify”
                                oOutput.WriteLine “replace: “ & sParm
                                oOutput.WriteLine sParm & “: “ & sValue
                                oOutput.WriteLine “-“
                                oOutput.WriteLine “”
                    end select
                  end if
      end select
    end if
  Loop
  oInput.Close
  oOutput.Close
  set oInput = nothing
  set oOutput = nothing
  if bDelSource then
    oFSO.DeleteFile(sInput)
  end if
  set oFSO = nothing
end sub
 
sub ShowUsage
  WScript.Echo “ModifyLdif.vbs <inputfile.ldf> [<outputfile.ldf> [<deleteinput>]]”
  WScript.Echo ”  inputfile:   Filename of the inputfile”
  WScript.Echo ”  outputfile:  Filename of the outputfile”
  WScript.Echo ”               If not provided, the filename of the inputfile”
  WScript.Echo ”               will be prefixed with a ““mod_”“”
  WScript.Echo ”  deleteinput: True or False (default), if True the inputfile”
  WScript.Echo ”               will be deleted after the outputfile is written”
  WScript.Quit
end sub

 


Feel free to use this at your own risk [;)]



2 Responses to “A Directory Services Geek’s View on Active Directory Recovery in Windows Server 2008”

  1.   Danijel Says:

    great Script 🙂

    Reply

  2.   BrianB Says:

    This was one of the most beneficial session of the conference. I can’t wait for the Slide Deck to come out. Thanks Ulf!

    Reply

Leave a Reply