none
Getting AD group members RRS feed

  • Question

  • function Get-LocalGroupMember {
        [CmdletBinding()]
    
        param(
        [parameter(ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)]
        [string[]]$ComputerName = $env:COMPUTERNAME
        )
    
        BEGIN {
            Add-Type -AssemblyName System.DirectoryServices.AccountManagement
            $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
        }
    
        PROCESS{
            foreach ($Computer in $ComputerName) {
                $Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $Computer
                $IDType = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
                $Group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $IDType, 'Administrators')
                $Group.Members |
                select @{N='Server'; E={$Computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName
            }
    
        } 
    
    }
    
    
    #This script is used in support of SOx requirement 1.3.4
    #$PathToScript = "C:\Users\ttyg3\OneDrive - Tronox\Documents\Scripts\1.7.4 IT SOX - OS PASSWORD PARAMETERS"
    
    $ReportDate = Get-Date -Format yyyy-MM-dd
    
    #Create a folder according to the current date to be used for storing the report
    New-Item -Path ".\$ReportDate" -ItemType Directory
    
    $SystemList = Import-Csv ".\SystemList.csv"
    
    foreach ($System in $SystemList) {
    
        #Get all members of the local administrators group and assign to a variable
        $LocalSysAdmins = Get-LocalGroupMember -ComputerName $System.SystemName
        
        #Export the array of local group adminstrators to a file
        $LocalSysAdmins | Export-Csv ".\$ReportDate\$System Local Administrators Group $ReportDate.csv" -NoTypeInformation
        
        #Get all of the members of all domain groups found in the administrators group and export to a file
        $LocalSysAdminsInDomain = $LocalSysAdmins | Where-Object {$_.Domain -eq "Global.Tronox.Com"}
        
        $LocalSysAdminsInDomain | foreach {
            Get-ADGroupMember -Identity $_.SamAccountName -Recursive | <#Get-ADUser -Properties Enabled |#> Export-Csv ".\$ReportDate\$System Local Administrators Group Domain-Resolved $ReportDate.csv" -NoTypeInformation
        }
    
    }

    I'm reposting my code in a later post below.

    I have a requirement to produce a report of all local admins.  That includes listing the members of any domain groups found in the local admins group.  My code works fine up until the very last part where I use the get-adgroupmember cmdlet.  I can't take full credit for the code though.  I took the function found on the scripting guy blog and built on top of it.

    http://blogs.technet.com/b/heyscriptingguy/archive/2013/10/27/the-admin-s-first-steps-local-group-membership.aspx

    Any help as always is appreciated.





    Friday, May 22, 2015 4:41 PM

Answers

  • There doesn't have to be a requirement for enforcement.

    Compliance is best attained by policy when possible. GPO is designed for this.

    Organize the GPO hierarchy as needed and apply appropriate GPOs to configure correct memberships.

    Automatic compliance and reporting in one step.

    I don't think we will be able to fix your script for you here, as that's not really the purpose of this forum.

    If you insist on a scripting solution, my recommendation would be to hire a consultant to design a correct script for you.


    -- Bill Stewart [Bill_Stewart]

    Tuesday, May 26, 2015 4:26 PM
    Moderator

All replies

  • This script will probably be easier to use:

    Weekend Scripter: Who are the Administrators?


    -- Bill Stewart [Bill_Stewart]

    Friday, May 22, 2015 4:49 PM
    Moderator
  • I appreciate the post Bill!  However, your script seems to be doing essentially the same thing that Richard Siddaway's script is doing.  Your code might be more efficient, but that's not where my problem is.  My problem is piping the content from the code I posted above into the get-adgroupmember.  If I comment out the problematic code, it works fine.  If the code is included, the below error is thrown for each ad group member in the loop:

    Get-ADGroupMember : Cannot convert 'System.Object[]' to the type 'Microsoft.ActiveDirectory.Management.ADGroup' required by parameter 'Identity'. Specified method is not supported.

    At C:\Users\ttyg3\OneDrive - Tronox\Documents\Scripts\1.3.4 IT SOX – OS Administration\Get-LocalGroupMember.ps1:51 char:37

    +         Get-ADGroupMember -Identity $LocalSystemAdministratorsInDomain.SamAccoun ...

    +                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        + CategoryInfo          : InvalidArgument: (:) [Get-ADGroupMember], ParameterBindingException

        + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember

    Friday, May 22, 2015 5:26 PM
  • I may have stumpled upon something.  I think it's the method of passing the SamAccountName to the get-adgroupmember, it's not exactly in the format that the cmdlet is expecting it in... I'll play around with this more and post an update with my findings.
    Friday, May 22, 2015 6:09 PM
  • Yep, some of the SamAccountNames that are AD groups have spaces in them... Trying to figure out how to overcome this.

    Example: Domain Admins is the SamAccountName returned in each of the systems that I'm querying and obviously has a space, so the script isn't liking that.

    Friday, May 22, 2015 6:20 PM
  • It would help if you specified exactly what your goal/purpose is, instead of vague ideas about problems.

    By this I mean: What exactly are you expecting the output to look like?


    -- Bill Stewart [Bill_Stewart]


    Friday, May 22, 2015 6:46 PM
    Moderator
  • I am expecting two files to be generated, per system that is found in the csv file that is being imported.

    One file name looks like this: "@{SystemName=mysystemnamehere} Local Administrators Group 2015-05-22.csv"

    The content of that file looks like the below, which includes local accounts and domain accounts and domain groups:

    Domain             SamAccountName

    ------                  --------------

    WIN12R2         Administrator

    Manticore.org   Domain Admins

    Manticore.org   Richard 

    The other file name for that system looks like this: "@{SystemName=mysystemnamehere} Local Administrators Group Domain-Resolved 2015-05-22.csv"

    The content of that file would be the results from the very last line in my code:

    Get-ADGroupMember -Identity $_.SamAccountName -Recursive | Export-Csv ".\$ReportDate\$System Local Administrators Group Domain-Resolved $ReportDate.csv" -NoTypeInformation

    So what that code is doing is taking the SamAccountName property in the previous example and piping it into Get-ADGroupMember, and is recursing it to account for any nested AD groups.  The output of Get-ADGroupMember is being piped to Get-ADUser and showing the Enabled property because I need to know if the AD account is either endabled or disabled.




    Friday, May 22, 2015 7:02 PM
  • Get-AdGroupMember -Identity $_.SamAccountName -rec

    My guess is that you do not have a legitimate CSV file and you are getting crap in the gap.

    Write $_.SamAccountNAme to the console to see what it contains.

    To prove that the spaces in the names mean nothing do this:

    $samname='domain users'
    get-AdGroupMember $samname


    \_(ツ)_/

    Friday, May 22, 2015 7:21 PM
  • This won't work:

    $samname='domain users  '
    get-AdGroupMember $samname

    So we do this:

    $samname='domain users  '
    get-AdGroupMember $samname.Trim()

    For you we would do this:

    Get-AdGroupMember -Identity $_.SamAccountName.Trim() -rec


    \_(ツ)_/

    Friday, May 22, 2015 7:23 PM
  • Unless I'm mistaken, it looks like all the trim method with no arguments does is take off all leading and trailing spaces.  The space that is occurring is in the middle, and it should remain there because that will be the text that I'm looking up in AD.  I wouldn't be able to find a group in AD called "DomainAdmins"
    Friday, May 22, 2015 8:26 PM
  • Unless I'm mistaken, it looks like all the trim method with no arguments does is take off all leading and trailing spaces.  The space that is occurring is in the middle, and it should remain there because that will be the text that I'm looking up in AD.  I wouldn't be able to find a group in AD called "DomainAdmins"

    That is what it is supposed to do and that works.  Have you even tried it. Have you looked at the contents of your CSV?

    \_(ツ)_/

    Friday, May 22, 2015 8:36 PM
  • Yes I have tried it with no success and the second csv where it's doing the get-adgroupmember and outputting to csv is completely empty.
    Friday, May 22, 2015 8:42 PM
  • Also, I'm not familiar with how to pause a script to debug it to determine the value of a variable in the middle of a loop. I'm researching how to do this right now...
    Friday, May 22, 2015 8:47 PM
  • Also, I'm not familiar with how to pause a script to debug it to determine the value of a variable in the middle of a loop. I'm researching how to do this right now...

    You are still not answering the question.  What is the output of the name when you output it to the console.

    Write-Host 'SAMNAME: $($_.samaccountname)" -for green
    Get
    -ADGroupMember -Identity $_.SamAccountName -Recursive |
         Export-Csv ".\$ReportDate\$System Local Administrators Group Domain-Resolved $ReportDate.csv" -NoTypeInformation

    Run that and tell us what you see.


    \_(ツ)_/


    • Edited by jrv Friday, May 22, 2015 10:28 PM
    Friday, May 22, 2015 9:27 PM
  • Also, I'm not familiar with how to pause a script to debug it to determine the value of a variable in the middle of a loop. I'm researching how to do this right now...
    Just place a simple output statement in the loop and look at what it prints.

    \_(ツ)_/


    • Edited by jrv Friday, May 22, 2015 10:28 PM
    Friday, May 22, 2015 9:28 PM
  • ok so here's the results of including the write-host.  I get the name of the account that is currently in the $_.samaccountname, as I would have expected.

    Here's another example.  I have an AD group with a SamAccountName of SAP Admins that is returned for a system and does properly get reported in the file

    $SystemLocal Administrators Group $ReportDate.csv

    However, when I look at the corresponding file where I'm doing the get-adgroup, there's nothing in it.

    $SystemLocal Administrators Group Domain-Resolved $ReportDate

    Yet when I look at another system that has that same exact group SAP Admins showing in the file

    $SystemLocal Administrators Group $ReportDate.csv

    and then I look at the corresponding file $SystemLocal Administrators Group Domain-Resolved $ReportDate

    It's populated with the members of this group.

    Also for each system, I find the Domain Admins group in the first file, but never find the results of the get-adgroupmember in the second file.  The same is true with my Global_Server_Admin group.

    Yet, when I do an explicit get-adgroupmember -identity GROUPNAME command on each of these groups, every time they give me the results, the members of those groups.


    Friday, May 22, 2015 10:31 PM
  • There is absolutely no way to understand what you are talking about.  You are just rambling about things that none of us can know.  You need to post a specific couple of lines of code and ask a question.  You then need too follow through on that issue.  Currently you are  erratically jumping all over the place.


    \_(ツ)_/

    Friday, May 22, 2015 10:58 PM
  • ok let me try giving specific server names, account names and group names to see if that helps any.

    There is a server called Server01.  Running through my code, a file is created as follows:

    @{SystemName=Server01} Local Administrators Group 2015-05-22.csv

    The contents of the file are as follows:

    Server Domain SamAccountName
    Server01 Server01 Administrator
    Server01 subdomain.example.com Domain Admins
    Server01 subdomain.example.com   SAP Admins

    Server01     subdomain.example.com  Server_Admins

    There is another file generated, named as follows:

    @{SystemName=Server02} Local Administrators Group Domain-Resolved 2015-05-22.csv

    The contents of this file are completely blank.

    There is another server called Server02.  Running through my code, a file is created as follows:

    @{SystemName=Server02} Local Administrators Group 2015-05-22.csv

    The contents of the file are as follows:

    Server Domain SamAccountName
    Server02 Server01 Administrator
    Server02 subdomain.example.com Domain Admins
    Server02 subdomain.example.com   SAP Admins

    Server02     subdomain.example.com  Server_Admins

    There is another file generated, named as follows:

    @{SystemName=Server02} Local Administrators Group Domain-Resolved 2015-05-22.csv

    The contents of the file are as follows:

    DistinguishedName Enabled GivenName Name ObjectClass ObjectGUID SamAccountName SID Surname UserPrincipalName
    CN=smith\, Joe (Administrator),OU=Secured   IDs,OU=Security,DC=subdomain,DC=example,DC=Com TRUE Joe smith, Joe (Administrator) user 521de0b4-2d78-425a-835c-e0afed5191a4 TMYA4S S-1-5-21-944225532-1711431899-2483406219-57854 smith TMYA4S@subdomain@example.com
    CN=Shields\, mary   (Administrative),OU=Secured IDs,OU=Security,DC=subdomain,DC=example,DC=Com FALSE mary Shields, mary (Administrative) user 067b2e54-6525-4914-af2a-7b8d2843c513 TSYL7S S-1-5-21-944225532-1711431899-2483406219-55208 Shields TSYL7S@subdomain@example.com

    These two people are found in the SAP Admins group

    You'll notice there is no one listed in this file for the Domain Admins group or the Server_Admins group, even though when I check these groups in AD, these groups do contain actual user objects.

    So you can see in one instance, the below code worked for one three groups found on one of the servers in the local administrators group for server02

    Get-ADGroupMember -Identity $_.SamAccountName.trim() -Recursive | Get-ADUser -Properties Enabled | Export-Csv ".\$ReportDate\$System Local Administrators Group Domain-Resolved $ReportDate.csv" -NoTypeInformation

    But that same code in that same loop returned nothing at all for server01, even though I have a persistent connection to my network and the domain controller's database that is being queried against.




    Friday, May 22, 2015 11:34 PM
  • Last time.

    Try this:

    Get-AdGroupMember 'Domain Admins'

    Does it work?

    Now explain why the contents of your file contain items that don't work.

    Your file is not a legal CSV and its contents are not what you think.  No matter how complex your explanation is you will still have to solve these problems.


    \_(ツ)_/

    Friday, May 22, 2015 11:43 PM
  • I would also suggest that if the ultimate purpose is to enforce the membership of the Administrators group on multiple computers in the domain, there are GPOs that will do this for you. If you go the GPO route, all you have to do is look at the GPO for your report. In this way there is no need to hit all computers and try to resolve recursive group memberships.

    -- Bill Stewart [Bill_Stewart]

    Tuesday, May 26, 2015 2:25 PM
    Moderator
  • Thanks Bill! There actually is no enforcement required. This is part of a SOx compliance requirement, where there's only about 10 servers that we must perform this action for, twice a year.

    Going back to what jrv was mentioning, I did more analysis on what's going on now that time permitted itself.

    I have the following code that imports a csv file. 

    $PrincipalList = Import-Csv ".\Server01 Local Administrators Group.csv" foreach ($Principal in $PrincipalList) { #Get all of the members of all domain groups found in the administrators group and export to a file $LocalSysAdminsInDomain = $Principal | Where-Object {$Principal.Domain -eq "Subdomain.Example.Com"} | Select-Object {$Principal.SamAccountName,$Principal.Domain} $LocalSysAdminsInDomain

    $LocalSysAdminsInDomain.SamAccountName

    Get-ADGroupMember -Identity $LocalSysAdminsInDomain.SamAccountName }

    When I output the contents of $LocalSysAdminsInDomain, it provides it in the following exact format:

    {SAP_EPA_GlobalAdmin, Subdomain.Example.Com}

    Followed by the same error I mentioned previously, which is:

    Get-ADGroupMember : Cannot validate argument on parameter 'Identity'. The argument is null or empty.

    Provide an argument that is not null or empty, and then try the command again.

    When I try to output something like $LocalSysAdminsInDomain.SamAccountName, it outputs absolutely nothing.  It looks like I'm referencing my variable properties incorrectly.  I'm going to continue to look at what I'm doing wrong but if anyone recognizes it before I do, that would be awesome too :)

    Tuesday, May 26, 2015 4:23 PM
  • There doesn't have to be a requirement for enforcement.

    Compliance is best attained by policy when possible. GPO is designed for this.

    Organize the GPO hierarchy as needed and apply appropriate GPOs to configure correct memberships.

    Automatic compliance and reporting in one step.

    I don't think we will be able to fix your script for you here, as that's not really the purpose of this forum.

    If you insist on a scripting solution, my recommendation would be to hire a consultant to design a correct script for you.


    -- Bill Stewart [Bill_Stewart]

    Tuesday, May 26, 2015 4:26 PM
    Moderator