AD Security Group Query

Discussion in 'Software' started by Alex Wright, Aug 5, 2009.

  1. Alex Wright

    Alex Wright Megabyte Poster

    501
    9
    57
    Hi,

    I am currently in the process of planning which security groups to migrate across to my company's new domain. What I am lookling for is a piece of software that when run, lists all of the security groups that are currently in use on our network. In other words, I don't want to migrate across any groups that are in effect, surpless to requirements.

    As yet, I haven't been able to find any software that can do this. But I was hoping that a scripting language such as Powershell would be capable of finding out this information?

    I am grateful for any advice that you can give.

    Alex
     
    Certifications: 70-680 Configuring Windows 7
    WIP: 70-642
  2. Fergal1982

    Fergal1982 Petabyte Poster

    4,196
    172
    211
    One of my colleagues here wrote a script that will search a given directory structure, and list the security groups on it. Hes not in at the moment, but ill see if i can get it for you.
     
    Certifications: ITIL Foundation; MCTS: Visual Studio Team Foundation Server 2010, Administration
    WIP: None at present
  3. Qs

    Qs Semi-Honorary Member Gold Member

    3,081
    70
    171
    Can't you do this using dsquery, or am I getting the wrong end of the stick?

    Qs
     
    Certifications: MCT, MCSE: Private Cloud, MCSA (2008), MCITP: EA, MCITP: SA, MCSE: 2003, MCSA: 2003, MCITP: EDA7, MCITP: EDST7, MCITP: EST Vista, MCTS: Exh 2010, MCTS:ServerVirt, MCTS: SCCM07 & SCCM2012, MCTS: SCOM07, MCTS: Win7Conf, MCTS: VistaConf, MCDST, MCP, MBCS, HND: Applied IT, ITIL v3: Foundation, CCA
  4. Alex Wright

    Alex Wright Megabyte Poster

    501
    9
    57
    dsquery is a part of Windows Server 2008. We currently use 2003 - is there something similar for this?
     
    Certifications: 70-680 Configuring Windows 7
    WIP: 70-642
  5. Fergal1982

    Fergal1982 Petabyte Poster

    4,196
    172
    211
    dsquery wont really work. The OP wants to know (as i understand it) all of the security groups being applied to directory security in his environment. dsquery would just list the groups currently in AD. not whether they are in use.
     
    Certifications: ITIL Foundation; MCTS: Visual Studio Team Foundation Server 2010, Administration
    WIP: None at present
  6. Alex Wright

    Alex Wright Megabyte Poster

    501
    9
    57
    That's exactly what I'd like to know.
     
    Certifications: 70-680 Configuring Windows 7
    WIP: 70-642
  7. Fergal1982

    Fergal1982 Petabyte Poster

    4,196
    172
    211
    dsquery is available on win server 2003 too. You just need to install the resource pack I believe
     
    Certifications: ITIL Foundation; MCTS: Visual Studio Team Foundation Server 2010, Administration
    WIP: None at present
  8. Qs

    Qs Semi-Honorary Member Gold Member

    3,081
    70
    171
    Dsquery is included in Win 2K3 too! :wink:

    You could query AD groups using last changed date though and export it to a text file...

    E.G. DSQuery * "OU=EXAMPLEOU,DC=EXAMPLE,DC=EXAMPLE" -Filter "(objectCategory=group)" -Attr Name whenChanged -Limit 0 >C:\TextFile.txt

    Right?

    Qs
     
    Certifications: MCT, MCSE: Private Cloud, MCSA (2008), MCITP: EA, MCITP: SA, MCSE: 2003, MCSA: 2003, MCITP: EDA7, MCITP: EDST7, MCITP: EST Vista, MCTS: Exh 2010, MCTS:ServerVirt, MCTS: SCCM07 & SCCM2012, MCTS: SCOM07, MCTS: Win7Conf, MCTS: VistaConf, MCDST, MCP, MBCS, HND: Applied IT, ITIL v3: Foundation, CCA
  9. Qs

    Qs Semi-Honorary Member Gold Member

    3,081
    70
    171
    Included out of the box iirc.

    Qs
     
    Certifications: MCT, MCSE: Private Cloud, MCSA (2008), MCITP: EA, MCITP: SA, MCSE: 2003, MCSA: 2003, MCITP: EDA7, MCITP: EDST7, MCITP: EST Vista, MCTS: Exh 2010, MCTS:ServerVirt, MCTS: SCCM07 & SCCM2012, MCTS: SCOM07, MCTS: Win7Conf, MCTS: VistaConf, MCDST, MCP, MBCS, HND: Applied IT, ITIL v3: Foundation, CCA
  10. Fergal1982

    Fergal1982 Petabyte Poster

    4,196
    172
    211
    That just tells you what has been changed on the server, and/or groups that exist in AD. It wont tell you which groups are actually in use.

    i.e. I can create a group today. Your query will list it, even if its not in use on a directory.
     
    Certifications: ITIL Foundation; MCTS: Visual Studio Team Foundation Server 2010, Administration
    WIP: None at present
  11. Qs

    Qs Semi-Honorary Member Gold Member

    3,081
    70
    171
    I guess. At the very least you could use the output to differentiate between the last changed date on the groups, so that it provides some guidance on what to chop.

    A dsquery listing empty groups (which you could then remove) would also be useful.

    Suffice it to say, it's a ballache unless you found some crazy LDAP query to run which did it for you. *shrugs*

    See what Fergal's colleauge can come up with.

    Qs
     
    Certifications: MCT, MCSE: Private Cloud, MCSA (2008), MCITP: EA, MCITP: SA, MCSE: 2003, MCSA: 2003, MCITP: EDA7, MCITP: EDST7, MCITP: EST Vista, MCTS: Exh 2010, MCTS:ServerVirt, MCTS: SCCM07 & SCCM2012, MCTS: SCOM07, MCTS: Win7Conf, MCTS: VistaConf, MCDST, MCP, MBCS, HND: Applied IT, ITIL v3: Foundation, CCA
  12. zebulebu

    zebulebu Terabyte Poster

    3,748
    330
    187
    As usual, Scripting Guy to the rescue:

    Code:
    On Error Resume Next
    
    Const ADS_SCOPE_SUBTREE = 2
    
    Set objConnection = CreateObject("ADODB.Connection")
    Set objCommand =   CreateObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    Set objCommand.ActiveConnection = objConnection
    
    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
    
    objCommand.CommandText = _
        "SELECT Name FROM 'LDAP://dc=fabrikam,dc=com' WHERE objectCategory='group'" & _
            "AND groupType = -2147483640" 
    Set objRecordSet = objCommand.Execute
    
    objRecordSet.MoveFirst
    Do Until objRecordSet.EOF
        Wscript.Echo objRecordSet.Fields("Name").Value
        objRecordSet.MoveNext
    Loop
    Try that
     
    Certifications: A few
    WIP: None - f*** 'em
  13. Fergal1982

    Fergal1982 Petabyte Poster

    4,196
    172
    211
    Zeb, that doesnt tell you which of those groups are actually in use in the environment, which is what the OP is looking for. He wants to know, of all the groups in his domain, which are actually being used currently, so he can avoid transferring over dead groups.
     
    Certifications: ITIL Foundation; MCTS: Visual Studio Team Foundation Server 2010, Administration
    WIP: None at present
  14. Qs

    Qs Semi-Honorary Member Gold Member

    3,081
    70
    171
    ...will have the same limitation as my dsquery suggestions - active groups can't be differentiated from inactive groups.

    Qs
     
    Certifications: MCT, MCSE: Private Cloud, MCSA (2008), MCITP: EA, MCITP: SA, MCSE: 2003, MCSA: 2003, MCITP: EDA7, MCITP: EDST7, MCITP: EST Vista, MCTS: Exh 2010, MCTS:ServerVirt, MCTS: SCCM07 & SCCM2012, MCTS: SCOM07, MCTS: Win7Conf, MCTS: VistaConf, MCDST, MCP, MBCS, HND: Applied IT, ITIL v3: Foundation, CCA
  15. Alex Wright

    Alex Wright Megabyte Poster

    501
    9
    57
    I appreciate the reply Zeb, but the script above doesn't help me with what I'm trying to achieve. I don't want to list, or indeed, count the groups that are in my domain. What I'd like to know is which groups are being applied to the directory security, i.e which groups are being used to control access to specific folders on our network.

    I hope that makes sense.

    Cheers,

    A
     
    Certifications: 70-680 Configuring Windows 7
    WIP: 70-642
  16. zebulebu

    zebulebu Terabyte Poster

    3,748
    330
    187
    Ah - you mean something that will enumerate all security groups then list all their members? Or do you just want to enumerate security groups used in folder ACLs?

    EDIT: You might want to look at this - I used it in a migration a while back for a couple of tasks and it was pretty useful (took me ages to remember what it was called!)
     
    Certifications: A few
    WIP: None - f*** 'em
  17. Alex Wright

    Alex Wright Megabyte Poster

    501
    9
    57
    Just the groups used in Access Control Lists. We have no requirements for the others.

    Thanks for the link, I'll take a look now. :)
     
    Certifications: 70-680 Configuring Windows 7
    WIP: 70-642
  18. Alex Wright

    Alex Wright Megabyte Poster

    501
    9
    57
    Hi Fergal1982,

    Have you had an opportunity to speak with your colleague regarding the script?

    Thanks,

    Alex
     
    Certifications: 70-680 Configuring Windows 7
    WIP: 70-642
  19. Fergal1982

    Fergal1982 Petabyte Poster

    4,196
    172
    211
    Ok, here is the script that he supplied me, and points beneath.

    Code:
    Const ForReading = 1
    Const HIDDEN = 2
    compareString = ""
    currentString = ""
    Dim currentArray()
    Dim strDomain
    Public fso
    set fso = CreateObject ("Scripting.FileSystemObject")
    Set outputFile = fso.CreateTextFile ("listsecuritygroups.txt", True)
    Set outputFile2 = fso.CreateTextFile ("listsecuritypermresdetail.csv", True)
    Set outputFile3 = fso.CreateTextFile ("listsecurityerror.txt", True)
    Public objDict,objDict3
    set objDict = CreateObject("Scripting.Dictionary")
    set objDict3 = CreateObject("Scripting.Dictionary")
    Set WshNetwork = WScript.CreateObject("WScript.Network")
    ' Run the function
    call IndexScripts
    'msgbox "Done perm"
    sub IndexScripts()
        dim loc
        loc = InputBox("Please enter path to extract security info from.")
        strDomain = InputBox("Please enter Domain name prefix.")
    '    if WScript.Arguments.Count = 0 then
    '        loc = fso.GetAbsolutePathName(".")
    '    else
    '        loc = WScript.Arguments(0)
    '    end if
        If loc = "" Then Wscript.Quit
        If fso.FolderExists(loc) Then
          GetWorkingFolder loc, 0, 1, "|"
        Else
          msgbox "Invalid folder path"
          Wscript.quit
        End If
        set fso = nothing
        
    End Sub
    ' called recursively to get a folder to work in
    function GetWorkingFolder(foldspec, foldcount, firsttime, spacer)
        Dim objShell,oExec
        Set objShell = CreateObject("WScript.Shell")
        
        dim fso
        Set fso = CreateObject("Scripting.FileSystemObject")
        dim fold
        set fold = fso.GetFolder(foldspec)
        
        dim foldcol
        set foldcol = fold.SubFolders
        
        'do the first folder stuff
        if firsttime = 1 then
          preDelimiter = ""
          If (Fold.Attributes And HIDDEN) and right(fold.path,2) <> ":\" Then
            outputFile3.WriteLine "Hidden folder," & fold.path
          Else
          'execute cacls to display ACL information, removing \ if starting at drive level (s:\)
          If right(fold.path,2) = ":\" Then
            Set oExec = objShell.Exec("cacls " & chr(34) & left(fold.path,len(fold.path) -1) & chr(34))
          Else
            Set oExec = objShell.Exec("cacls " & chr(34) & fold.path & chr(34))
          End If
            dim firstline
            firstline=1
            Do While Not oExec.StdOut.AtEndOfStream
                 Dim str
                 str = oExec.StdOut.ReadLine
                 'Remove any carriage returns.
                 str = replace(str,VBCR,"")
                 'First line need to split into folder path and security
                 If firstline = 1 Then
                   firstline = 0
                   'Find where security starts
                   splitpoint = 0
                   If InstrRev(str,strDomain & "\") > splitpoint Then splitpoint = InstrRev(str, strDomain & "\")
                   If InstrRev(str,WshNetwork.ComputerName & "\") > splitpoint Then splitpoint = InstrRev(str,WshNetwork.ComputerName & "\")
                   If InstrRev(str,"BUILTIN\") > splitpoint Then splitpoint = InstrRev(str,"BUILTIN\")
                   If InstrRev(str,"NT AUTHORITY\") > splitpoint Then splitpoint = InstrRev(str,"NT AUTHORITY\")
                   If InstrRev(str,"<Account Domain") > splitpoint Then splitpoint = InstrRev(str,"<Account Domain")
                   If InstrRev(str,"Everyone") > splitpoint Then splitpoint = InstrRev(str,"Everyone")
                   permPath = left(str,splitpoint - 2)
                   'Need to remove the \ for drive level
                   If right(permPath,2) = ":\" Then permPath = left(permPath,len(permPath) - 1)
                   wscript.echo permPath
                   'Want to ignore non-existant accounts and groups, and Creator Owner
                   If (InStr(str,"Account Domain not found") = 0) and (InStr(str,"CREATOR") = 0) Then
                     currentString = trim(mid(str,splitpoint,len(str)))
                     If (InStr(trim(mid(str,splitpoint,len(str))),":") > 0) and (InStr(trim(mid(str,splitpoint,len(str))),":)") = 0) Then currentString = currentString & ";"
                     If InStr(trim(mid(str,splitpoint,len(str))),":)") > 0 Then preDelimiter = ";"
                   Else
                     currentString = ""
                   End If
                   strRecord = trim(mid(str,splitpoint,len(str)))
                 Else
                   'Only security on this line
                   'Want to ignore non-existant accounts and groups, and Creator Owner
                   If (InStr(str,"Account Domain not found") = 0) and (InStr(str,"CREATOR") = 0) Then
                     'Append security to others
                     If (InStr(trim(str),":") > 0) and preDelimiter = ";" Then
                       currentString = currentString & preDelimiter & trim(str)
                       preDelimiter = ""
                     Else
                       currentString = currentString & trim(str)
                     End If
                     If (InStr(trim(str),":") > 0) and preDelimiter = ";" Then preDelimiter = ""
                     If (InStr(trim(str),":") > 0) and (InStr(trim(str),":)") = 0) Then currentString = currentString & ";"
                     If InStr(trim(str),":)") > 0 Then preDelimiter = ";"
                     strRecord = trim(str)
                   End If
                 End If
                 If strRecord > "" Then
                   'Want to ignore non-existant accounts and groups, and Creator Owner
                   If (InStr(str,"Account Domain not found") = 0) and (InStr(str,"CREATOR") = 0) Then 
                     'Add group/user to listsecuritygroups.txt if not already there.
                     If InStr(strRecord,":") > 0 Then
                       arrRecord = split(strRecord,":")
                       strAdd = arrRecord(0)
                       If objDict.exists(lcase(strAdd)) = False Then
                         objDict.add lcase(strAdd), strAdd
                         outputFile.WriteLine strAdd
                       End If
                     End If
                   End If
                 End If
            Loop
            'Remove ; from end of security string
            if right(currentString,1) = ";" Then currentString = left(currentString,len(currentString) - 1)
            'Output path and security to listsecuritydetails.csv and add to list to compare back to
            outputFile2.WriteLine permPath & "," & currentString
            objDict3.add permPath, currentString
            End If
            set oExec = nothing
            
            foldcount = foldcol.count
            firsttime = 0
        
        End If
        'Folder path of 255 or more will give error in cacls, so skip if this is the case
        If len(fold.path) < 255 Then
          If (Fold.Attributes And HIDDEN) and right(fold.path,2) <> ":\" Then
            outputFile3.WriteLine "Hidden folder," & fold.path
          Else
            If (InStr(lcase(currentString),"administrators") > 0) or (InStr(lcase(currentString),"everyone") > 0) Then
              dim remaincount
              remaincount = foldcol.count
              'do the subfolder stuff
              dim sf
              for each sf in foldcol
                preDelimiter = ""
                    
                'execute cacls to display ACL information
                Set oExec = objShell.Exec("cacls " & chr(34) & sf.path & chr(34))
                firstline=1
            
                Do While Not oExec.StdOut.AtEndOfStream
                  str = oExec.StdOut.ReadLine
                  'Remove any carriage returns.
                  str = replace(str,VBCR,"")
                  x = 0
                  specialAccess = 0
                  matchStrings = 1
                  'First line need to split into folder path and security
                  If firstline = 1 Then
                    firstline = 0
                    'Find where security starts
                    splitpoint = 0
                    If InstrRev(str,"Everyone") > splitpoint Then splitpoint = InstrRev(str,"Everyone")
                    If InstrRev(str, strDomain & "\") > splitpoint Then splitpoint = InstrRev(str, strDomain & "\")
                    If InstrRev(str,WshNetwork.ComputerName & "\") > splitpoint Then splitpoint = InstrRev(str,WshNetwork.ComputerName & "\")
                    If InstrRev(str,"BUILTIN\") > splitpoint Then splitpoint = InstrRev(str,"BUILTIN\")
                    If InstrRev(str,"NT AUTHORITY\") > splitpoint Then splitpoint = InstrRev(str,"NT AUTHORITY\")
                    If InstrRev(str,"<Account Domain") > splitpoint Then splitpoint = InstrRev(str,"<Account Domain")
                    If splitpoint > 0 Then
                      permPath = left(str,splitpoint - 2)
                      wscript.echo permPath
                      'Want to ignore non-existant accounts and groups, and Creator Owner
                      If (InStr(str,"Account Domain not found") = 0) and (InStr(str,"CREATOR") = 0) Then
                        currentString = trim(mid(str,splitpoint,len(str)))
                        If (InStr(trim(mid(str,splitpoint,len(str))),":") > 0) and (InStr(trim(mid(str,splitpoint,len(str))),":)") = 0) Then currentString = currentString & ";"
                        If InStr(trim(mid(str,splitpoint,len(str))),":)") > 0 Then preDelimiter = ";"
                      Else
                        currentString = ""
                      End If
                      strRecord = currentString
                      'start array of security for comparision to parent folder
                      ReDim currentArray(x)
                      currentArray(x) = strRecord
                      x = x + 1
                    Else
                      'The point between path and security cannot be found
                      outputFile3.WriteLine "Unknown security," & str 
                      Exit Do
                    End If
                  Else
                    'Want to ignore non-existant accounts and groups, and Creator Owner
                    If (InStr(str,"Account Domain not found") = 0) and (InStr(str,"CREATOR") = 0) Then 
                      If (InStr(trim(str),":") > 0) and preDelimiter = ";" Then
                        currentString = currentString & preDelimiter & trim(str)
                        preDelimiter = ""
                      Else
                        currentString = currentString & trim(str)
                      End If
                      If (InStr(trim(str),":") > 0) and preDelimiter = ";" Then preDelimiter = ""
                      If (InStr(trim(str),":") > 0) and (InStr(trim(str),":)") = 0) Then currentString = currentString & ";"
                      If InStr(trim(str),":)") > 0 Then preDelimiter = ";"
                      strRecord = trim(str)
                      'expand array of security for comparision to parent folder
                      ReDim Preserve currentArray(x)
                      currentArray(x) = strRecord
                      x = x + 1
                    End If
                  End If
                  If strRecord > "" Then
                    'Want to ignore non-existant accounts and groups, and Creator Owner
                    If (InStr(str,"Account Domain not found") = 0) and (InStr(str,"CREATOR") = 0) Then 
                      'Add group/user to listsecuritygroups.txt if not already there.
                      If InStr(strRecord,":") > 0 Then
                        arrRecord = split(strRecord,":")
                        strAdd = arrRecord(0)
                        If objDict.exists(lcase(strAdd)) = False Then
                          objDict.add lcase(strAdd), strAdd
                          outputFile.WriteLine strAdd
                        End If
                      End If
                    End If
                  End If
                Loop
                If splitpoint > 0 Then
                  'Remove ; from end of security string
                  if right(currentString,1) = ";" Then currentString = left(currentString,len(currentString) - 1)
                  previousFolder = left(permPath, InStrRev(permPath,"\") -1)
                  'Check parent folder security has been stored
                  If objDict3.Exists(previousFolder) = true Then
                    'Start security comparison
                    compareString = objDict3.Item(previousFolder)
                    if Len(currentString) = Len(compareString) Then
                      For y = 0 to Ubound(currentArray)
                        If InStr(compareString,currentArray(y)) = 0 Then matchStrings = 0
                      Next
                    Else
                      matchStrings = 0
                    End If
                    If matchStrings = 0 Then
                      'Security different than parent folder
                      outputFile2.WriteLine permPath & "," & currentString
                      compareString = currentString
                    End If
                    objDict3.add permPath, currentString
                  End If
                End If
            
                set oExec = nothing
                remaincount = GetWorkingFolder (foldspec +"\"+sf.name, remaincount, firsttime, spacer)
              next 
            End If
          End If
        Else
          outputFile3.WriteLine "Long folder path," & fold.path
        End If
        
        'clean up
        set fso = nothing
        
        GetWorkingFolder = foldcount - 1
    end function
    
    Firstly, you need to run this from the command prompt (using cscript <filename>), otherwise you are going to get heaps of popups for every filepath.

    When you run it, it will ask you for the filepath. It wont accept UNC paths, so you either need to run it locally on the server (probably quicker and better on network performance), or map a drive on your computer to the start point.

    It will also ask you for your domain prefix, this is the bit that usually appears before the samaccountname (ie Test\Fergal1982 - prefix is Test). Its case sensitive so enter it as it is.

    The output comes in three files:

    listsecurityerror.txt - fairly obvious, lists all the folders it errored on.

    listsecuritygroups.txt - this is what I think you will be most interested in, it lists all of the security groups in use on the filepath supplied and subfolders.

    listsecuritypermresdetails.csv should list each folder and all of its permissions (groups and levels). If subfolders are the same permissions as the parent, it ignores them. In theory you can use this to rebuild permissions in the event of some sort of catastrophic failure.


    I believe you will find that it will fail because of path lengths too - ie, if the filepath from the start point to the target folder is more than (i think) 258 characters, it will fail on those folders. You can get around that by mapping a driver to the target folder, and running it against that drive.
     
    Certifications: ITIL Foundation; MCTS: Visual Studio Team Foundation Server 2010, Administration
    WIP: None at present
  20. Josiahb

    Josiahb Gigabyte Poster

    1,335
    40
    97
    This is something I was looking at a while ago, this script will make it a hell of a lot easier to keep track of AD groups. Thanks Fergal! :D
     
    Certifications: A+, Network+, MCDST, ACA – Mac Integration 10.10

Share This Page

Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.