Skip to content

Commit d022904

Browse files
committed
add Get-ADGroupMember,
rework ps1, add default username/password to integration script invoker
1 parent 73f6da7 commit d022904

File tree

4 files changed

+104
-7
lines changed

4 files changed

+104
-7
lines changed

src/ADServices/ADGroupMember.psm1

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ function Remove-ADGroupMember {
7979
Nothing, unless PassThru is set in which case it returns the Group as a
8080
[DirectoryServices.DirectoryEntry].
8181
#>
82+
[OutputType([DirectoryServices.DirectoryEntry])]
8283
[CmdletBinding(SupportsShouldProcess)]
8384
param (
8485
# Identity of the group to add members to.
@@ -134,3 +135,46 @@ function Remove-ADGroupMember {
134135
}
135136
}
136137
}
138+
139+
140+
function Get-ADGroupMember {
141+
<#
142+
.SYNOPSIS
143+
Get Member ADObjects of a group.
144+
.OUTPUTS
145+
[DirectoryServices.DirectoryEntry] of the ADObjects within the group. If the group does not exist, returns Nothing.
146+
#>
147+
[OutputType([DirectoryServices.DirectoryEntry])]
148+
[CmdletBinding()]
149+
param(
150+
# Identity of the group.
151+
[Parameter(Mandatory, ValueFromPipeline)]
152+
[string] $Identity,
153+
154+
# The domain controller to query.
155+
[Parameter()]
156+
[string] $Server = $null,
157+
158+
# Credentials for the domain controller.
159+
[Parameter()]
160+
[PSCredential] $Credential = $null,
161+
162+
[switch] $Recursive
163+
)
164+
process {
165+
$group = Get-ADGroup -Identity $Identity -Server $Server -Credential $Credential -Verbose:$VerbosePreference
166+
if (-not $group) {
167+
return
168+
}
169+
$groupDN = $group.distinguishedName
170+
$members = Get-ADObject -LDAPFilter "(memberOf=$groupDN)" -Server $Server -Credential $Credential -Verbose:$VerbosePreference
171+
172+
# output
173+
$members
174+
if ($Recursive) {
175+
$members | Foreach-Object {
176+
Get-ADGroupMember -Identity $_.distinguishedName -Server $Server -Credential $Credential -Recursive
177+
}
178+
}
179+
}
180+
}

src/ADServices/ADServices.psd1

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
@{
2-
ModuleVersion = '0.1.1'
2+
ModuleVersion = '0.1.2'
33
GUID = 'c29c8e32-38a3-4ed4-acc3-11ad44bcab3c'
44
Author = 'Martin C Zarate (AKA Pxtl)'
55
Copyright = '2025, Martin C Zarate'
66
Description = @'
7-
Rough lightweight feature-incomplete drop-in replacement for some of the
8-
components of the MS ActiveDirectory module but leveraging the C#
9-
"System.DirectoryServices.dll" assembly which is available by default on Windows
10-
instead of requiring that the user install RSAT.
7+
Rough re-implementation of the MS ActiveDirectory powershell module but
8+
leveraging the C# "System.DirectoryServices.dll" assembly which is available by
9+
default on Windows instead of requiring that the user install RSAT. Very
10+
feature-incomplete at this time. Also, unfortunately
11+
"System.DirectoryServices.dll" is Windows-only and therefore so is this module.
1112
'@
1213

1314
# Minimum version of the Windows PowerShell engine required by this module
@@ -43,11 +44,15 @@ instead of requiring that the user install RSAT.
4344
ProjectUri = 'https://github.com/Pxtl/powershell-modules'
4445
# IconUri = ''
4546
ReleaseNotes = @'
47+
v0.1.2
48+
- add Get-ADGroupMember
49+
4650
v0.1.1
4751
- hide private functions properly
4852
4953
v0.1.0
5054
- Initial Version
55+
- Includes main verbs for ADObject, ADUser, ADAccount, ADGroup, ADGroupMember
5156
'@
5257
} # End of PSData hashtable
5358
} # End of PrivateData hashtable

src/ADServices/Tests/Integration/ADGroupMember.tests.ps1

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,51 @@ Describe 'ADGroup Membership' -Tags Integration {
100100
$loadedADGroup.member.Count | Should -Be 1
101101
}
102102

103+
It 'Can Get-ADGroupMember' {
104+
# prepare
105+
$groupCode = 4
106+
$testGroupName = "parentGroup$groupCode"
107+
$newGroup = New-ADGroup @ConnectionParam -Name $testGroupName -Verbose:$VerbosePreference -PassThru
108+
$newGroup.member.Count | Should -Be 0
109+
110+
$testUser1Name = "childUser1ForGroup$groupCode"
111+
$newUser1 = New-ADUser @ConnectionParam -Name $testUser1Name -Verbose:$VerbosePreference -PassThru
112+
$testUser2Name = "childUser2ForGroup$groupCode"
113+
$newUser2 = New-ADUser @ConnectionParam -Name $testUser2Name -Verbose:$VerbosePreference -PassThru
114+
$testChildGroupName = "childGroup$groupCode"
115+
$testChildGroup = New-ADGroup @ConnectionParam -Name $testChildGroupName -Verbose:$VerbosePreference -PassThru
116+
$testGrandchildUserName = "grandchildUser1ForGroup$groupCode"
117+
$grandchildUser = New-ADUser @ConnectionParam -Name $testGrandchildUserName -Verbose:$VerbosePreference -PassThru
118+
119+
# act
120+
Add-ADGroupMember @ConnectionParam -Identity $newGroup.distinguishedName -Members $newUser1.distinguishedName, $newUser2.distinguishedName, $testChildGroup.distinguishedName -Verbose:$VerbosePreference
121+
Add-ADGroupMember @ConnectionParam -Identity $testChildGroup.distinguishedName -Members $grandchildUser.distinguishedName -Verbose:$VerbosePreference
122+
123+
# examine
124+
125+
## test fetch from AD
126+
$members = Get-ADGroupMember @ConnectionParam -Identity $testGroupName -Verbose:$VerbosePreference
127+
$memberDNs = $members | ForEach-Object {
128+
$_.distinguishedName.Value
129+
}
130+
$memberDNs | Should -Contain "CN=childUser1ForGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
131+
$memberDNs | Should -Contain "CN=childUser2ForGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
132+
$memberDNs | Should -Contain "CN=childGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
133+
$memberDNs.Count | Should -Be 3
134+
135+
## test fetch from AD recursively
136+
$memberDNs = Get-ADGroupMember @ConnectionParam -Identity $testGroupName -Verbose:$VerbosePreference -Recursive |
137+
ForEach-Object {
138+
$_.distinguishedName.Value
139+
}
140+
$memberDNs | Should -Contain "CN=childUser1ForGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
141+
$memberDNs | Should -Contain "CN=childUser2ForGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
142+
$memberDNs | Should -Contain "CN=childGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
143+
$memberDNs | Should -Contain "CN=grandchildUser1ForGroup$groupCode,CN=Users,DC=samdom,DC=example,DC=com"
144+
$memberDNs.Count | Should -Be 4
145+
}
146+
147+
103148
AfterEach {
104149
Write-Verbose "Cleanup in $($MyInvocation.MyCommand.ScriptBlock.File | Split-Path -Leaf)."
105150
& "$PSScriptRoot\Shared\Clear-TestObjects.ps1"

src/ADServices/Tests/Integration/Invoke-IntegrationTest.ps1

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ param (
77
[PSCredential] $PSCredential
88
)
99

10+
if (-not $PSCredential) {
11+
# default credentials for smblds
12+
$PSCredential = [PSCredential]::new('Administrator', (ConvertTo-SecureString 'Passw0rd' -AsPlainText -Force))
13+
}
14+
1015
# prepare
11-
##########
1216
docker compose -f "$PSScriptRoot\adservices-testdocker\docker-compose.yml" up -d --wait
1317

1418
# refresh module version in memory then unload it to prevent accidental memory of old versions of module.
@@ -17,7 +21,6 @@ Import-Module $PSScriptRoot\..\..\Shared\ADHelpers.psm1 -Force -Verbose:$false |
1721
Import-Module $PSScriptRoot\..\..\Shared\ADDirectoryEntry.psm1 -Force -Verbose:$false | Remove-Module
1822

1923
# act
20-
######
2124
Invoke-Pester -Container (New-PesterContainer -ScriptBlock {
2225
& "$PSScriptRoot\ADUser.tests.ps1" -Server $Server -PSCredential $PSCredential
2326
& "$PSScriptRoot\ADAccount.tests.ps1" -Server $Server -PSCredential $PSCredential

0 commit comments

Comments
 (0)