Search code examples
powershellactive-directoryactive-directory-group

Powershell GPO Login Script checking AD resource group membership


The system I have to work with uses AD resource group membership to manage most of the permissions for users and computers. I have been asked to improve the current logon script as it currently contains some VB ADSISEARCHER calls. I started trying to do this purely in powershell but have hit a number of hurdles.

  • Target machines do not have the Active Directory Module installed
  • The users logging into the system have a restricted user accounts
  • The resource groups are nested so the script needs to handle this

I have tried a couple of approaches firstly the pure Powershell Cmdlet method of Get-ADGroup or Get-ADPricipalGroupMembership but these Cmdlet's require the Active Directory Module. Then I tried the .net approach with System.DirectoryServices.DirectoryEntry although this is a step away from a pure PowerShell solution at least it isn't as Legacy as the VB route. However when I try to build the object it also appears to be missing the name space.

First Attempt:

function Get-UserResourceMembership
{
    [CmdletBinding()]
    Param
    (
        # Username or Groupname to Discover Group Membership
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $User
    )

    Begin
    {
        $Groups = @(Get-ADPrincipalGroupMembership $User)
    }
    Process
    {
        foreach($ADGroup in $Groups)
            {
                if($ADGroup.ObjectClass -eq "Group")
                {
                    Get-UserResourceMembership $ADGroup
                }

                $GrpMembership = @($ADGroup)
            }
    }
    End
    {
     return ,$GrpMembership
    }
}

Second Attempt:

# $rootGroup is passed in from earlier in the script

$groupname = $rootGroup.'Group Name'
$filter = ("(&(objectCategory=Group)(name=$($groupname)))")
$searcher.Filter = $filter
$searcher.SearchScope = "Subtree"

$searchResults = $searcher.FindAll().GetDirectoryEntry().memberOf |
% { (New-Object System.DirectoryServices.DirectoryEntry("LDAP://"+$_)) } |
Sort-Object Children | select @{name="Group Name";expression={$_.Name}}

foreach($resource in $searchResults)
    {
        if($resource.'Group Name' -match "<Groupname>")
        {
            $printResource += $resource
        }
    }

Does anyone in the community have any suggestions how to pull group membership [nested] from Active Directory from a standard users login script??? Any idea's much appreciated....

PS I can't change the way the system is designed (above my pay grade).


Solution

  • As for ...

    • Target machines do not have the Active Directory Module installed

    • The users logging into the system have a restricted user accounts

    • The resource groups are nested so the script needs to handle this

    • Does not matter, they do not need to be installed on a client to use them. You can use PSRemoting to proxy those using 'Implicit Remoting'. The cmdlets are only available in the remote session.
    • Does not matter, as every user has read access, by default to ADDS in Windows.
    • You can get to those using the cmdlets you are using and there are even pre-built scripts in the Microsoft PowershellGallery.com for this as well.

    As for …

    I have tried a couple of approaches firstly the pure Powershell Cmdlet method of Get-ADGroup or Get-ADPricipalGroupMembership but these Cmdlet's require the Active Directory Module.

    As noted above, this can be addressed as described below:

    PowerShell Implicit Remoting: Never Install a Module Again

    Remote Session

    # create a session then import a module via the session, for example:
    $adsess = New-PSSession -ComputerName savdaldc01
    Import-Module -Name ActiveDirectory -PSSession $adsess
    Get-Module
    Get-ADUser -Filter *
    Remove-Module ActiveDirectory
    
    # It's also possible to prefix modules loaded from remote servers to differentiate from local modules, e.g.
    
    Import-Module -Name ActiveDirectory -PSSession $adsess -Prefix OnDC
    Get-OnDCADUser -Filter * #I don't have regular Get-ADUser anymore
    Remove-Module ActiveDirectory
    Remove-PSSession $adsess 
    

    As for ...

    Does anyone in the community have any suggestions how to pull group membership [nested]

    Get nested group membership - function

    This function will recursively enumerate members of a given group along with nesting level and parent group information. If there is a circular membership, it will be displayed in Comment column.It accepts input from pipeline and works well with get-adgroup. Download: Get-ADNestedGroupMembers.ps1

    As well as just doing this...

    We can get group members by using the Active Directory powershell cmlet Get-ADGroupMember. The Get-ADGroupMember cmdlet provides the option to get all the nested group members by passing the parameter -Recursive. This powershell script also handles circular membership (infinite loop) problem.

    Function Get-ADNestedGroupMembers 
    {
      [cmdletbinding()]
    
      param 
      ( 
          [String] $Group 
      )            
      Import-Module ActiveDirectory
      ($Members = Get-ADGroupMember -Identity $Group -Recursive)
    }
    
    Get-ADNestedGroupMembers "Domain Admins" | Select Name,DistinguishedName
    

    or this way.

    function Get-NestedGroupMember
    {
        param
        (
            [Parameter(Mandatory, ValueFromPipeline)]
            [string]$Identity
        )
    
        process
        {
            Import-Module ActiveDirectory
            $user = Get-ADUser -Identity $Identity
            $userdn = $user.DistinguishedName
            $strFilter = "(member:1.2.840.113556.1.4.1941:=$userdn)"
            Get-ADGroup -LDAPFilter $strFilter -ResultPageSize 1000
        }
    }