Skip to content

Commit 4ce0d6a

Browse files
authored
🐛 fix(scripts): resolve follow-up PowerShell audit findings (#16)
Resolve follow-up PowerShell audit and PR review findings.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a554187 commit 4ce0d6a

20 files changed

Lines changed: 299 additions & 135 deletions

Active Directory/AD Groups/Archive-ObsoleteGroups.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
#
1919
# ============================================================
2020

21-
#Import the Active Directory module so we can work with AD groups.
22-
Import-Module ActiveDirectory
23-
2421
# TODO: This script requires customization before running. The $Domain, archive paths,
2522
# TODO: group identity/OU values in the loop, and Move-ADObject target path must all be set
2623
# TODO: for your environment. See inline TODO comments below.
@@ -36,6 +33,9 @@ param (
3633
$GroupListPath = 'C:\Scripts\ObsoleteGroups\ObsoleteGroups.csv'
3734
)
3835

36+
#Import the Active Directory module so we can work with AD groups.
37+
Import-Module ActiveDirectory
38+
3939
#Read in the CSV or text file of group names.
4040
$File = Get-Content -Path $GroupListPath
4141

Active Directory/AD Users/Get-ADDirectReport.ps1

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
Specify that you want to retrieve all the indirect users under the account
2626
2727
.EXAMPLE
28-
Get-ADDirectReports -Identity Test_director
28+
Get-ADDirectReport -Identity Test_director
2929
3030
Name SamAccountName Mail Manager
3131
---- -------------- ---- -------
3232
test_managerB test_managerB test_managerB@la... test_director
3333
test_managerA test_managerA test_managerA@la... test_director
3434
3535
.EXAMPLE
36-
Get-ADDirectReports -Identity Test_director -Recurse
36+
Get-ADDirectReport -Identity Test_director -Recurse
3737
3838
Name SamAccountName Mail Manager
3939
---- -------------- ---- -------
@@ -56,7 +56,7 @@ test_userA1 test_userA1 test_userA1@lazy... test_managerA
5656
IF (-not (Get-Module -Name ActiveDirectory)) { Import-Module -Name ActiveDirectory -ErrorAction 'Stop' -Verbose:$false }
5757
} CATCH {
5858
Write-Verbose -Message '[BEGIN] Something wrong happened'
59-
Write-Verbose -Message $Error[0].Exception.Message
59+
Write-Verbose -Message $_.Exception.Message
6060
}
6161
}
6262
PROCESS {
@@ -69,9 +69,9 @@ test_userA1 test_userA1 test_userA1@lazy... test_managerA
6969
ForEach-Object -Process {
7070
$_.directreports | ForEach-Object -Process {
7171
# Output the current object with the properties Name, SamAccountName, Mail and Manager
72-
Get-ADUser -Identity $PSItem -Properties mail, manager, DistinguishedName | Select-Object -Property Name, SamAccountName, DistinguishedName, Mail, @{ Name = 'Manager'; Expression = { (Get-ADUser -Identity $psitem.manager).samaccountname } } | Where-Object { $_.DistinguishedName -like '*,OU=Employees,OU=People,DC=DOMAINNAME,DC=org' }
72+
Get-ADUser -Identity $PSItem -Properties mail, manager, DistinguishedName | Select-Object -Property Name, SamAccountName, DistinguishedName, Mail, @{ Name = 'Manager'; Expression = { (Get-ADUser -Identity $psitem.manager).samaccountname } }
7373
# Gather DirectReports under the current object and so on...
74-
Get-ADDirectReports -Identity $PSItem -Recurse
74+
Get-ADDirectReport -Identity $PSItem -Recurse
7575
}
7676
}
7777
}#IF($PSBoundParameters['Recurse'])
@@ -84,7 +84,7 @@ test_userA1 test_userA1 test_userA1@lazy... test_managerA
8484
}#TRY
8585
CATCH {
8686
Write-Verbose -Message '[PROCESS] Something wrong happened'
87-
Write-Verbose -Message $Error[0].Exception.Message
87+
Write-Verbose -Message $_.Exception.Message
8888
}
8989
}
9090
}
@@ -95,8 +95,8 @@ test_userA1 test_userA1 test_userA1@lazy... test_managerA
9595

9696
<#
9797
# Find all direct user reporting to Test_director
98-
Get-ADDirectReports -Identity Test_director
98+
Get-ADDirectReport -Identity Test_director
9999
100100
# Find all Indirect user reporting to Test_director
101-
Get-ADDirectReports -Identity Test_director -Recurse
101+
Get-ADDirectReport -Identity Test_director -Recurse
102102
#>

Active Directory/AD Users/Get-LockedOutLocation.ps1

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@
3333
try {
3434
Import-Module ActiveDirectory -ErrorAction Stop
3535
} catch {
36-
Write-Warning $_
37-
break
36+
throw "Failed to import the ActiveDirectory module. $($_.Exception.Message)"
3837
}
3938
}#end begin
4039
process {

Active Directory/Domain Services/DNSZonesRemote.ps1

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,31 @@ $Creds = Get-Credential
2929
#Loop through each server in the list, opening a PowerShell remoting session, then show the name and status of the session. Skips (continue) to the next server if a connection fails.
3030
foreach ($srv in $servers) {
3131
$server = $srv.Hostname
32-
$session = New-PSSession -ComputerName $server -Name $server -Credential $Creds
32+
$session = $null
3333
Try {
3434
Write-Host -ForegroundColor Green "Connecting to $server... " -NoNewline
35-
Enter-PSSession $session
36-
} Catch {
37-
Write-Host -ForegroundColor DarkYellow "Failed to enter the PSSession for $server. Skipping."
38-
Continue
39-
}
40-
Write-Output $session.State
35+
$session = New-PSSession -ComputerName $server -Name $server -Credential $Creds -ErrorAction Stop
36+
Write-Output $session.State
4137

42-
$zones = Get-ChildItem -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\DNS Server\Zones\'
38+
Invoke-Command -Session $session -ScriptBlock {
39+
$zones = Get-ChildItem -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\DNS Server\Zones\'
4340

44-
foreach ($zone in $zones) {
45-
Write-Host "`n`n 'Name: ' (Get-ItemProperty -PSPath $zone.PSPath).PSChildName" -NoNewline -ForegroundColor Yellow
46-
Write-Host "`n 'SecondaryServers: ' (Get-ItemProperty -PSPath $zone.PSPath).SecondaryServers" -NoNewline
47-
Write-Host "`n 'SecureSecondaries: ' (Get-ItemProperty -PSPath $zone.PSPath).SecureSecondaries `n" -NoNewline
41+
foreach ($zone in $zones) {
42+
Write-Host "`n`nName: $((Get-ItemProperty -PSPath $zone.PSPath).PSChildName)" -NoNewline -ForegroundColor Yellow
43+
Write-Host "`nSecondaryServers: $((Get-ItemProperty -PSPath $zone.PSPath).SecondaryServers)" -NoNewline
44+
Write-Host "`nSecureSecondaries: $((Get-ItemProperty -PSPath $zone.PSPath).SecureSecondaries) `n" -NoNewline
4845

49-
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecondaryServers" -Value "" -WhatIf
50-
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecureSecondaries" -Value "3" -WhatIf
46+
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecondaryServers" -Value "" -WhatIf
47+
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecureSecondaries" -Value "3" -WhatIf
48+
}
49+
}
50+
} Catch {
51+
Write-Host -ForegroundColor DarkYellow "Failed to enter the PSSession for $server. Skipping."
52+
Continue
53+
} Finally {
54+
if ($session) {
55+
Remove-PSSession $session
56+
Write-Host "$server session removed. `n`n" -ForegroundColor DarkYellow -NoNewline
57+
}
5158
}
52-
53-
#Cleanup and then show the current PSSession state.
54-
if ($session) { Exit-PSSession }
55-
if ($session) { Remove-PSSession $session }
56-
Write-Host "$session.ComputerName $session.State `n`n" -ForegroundColor DarkYellow -NoNewline
5759
}

Active Directory/Export-AllADUserTransitiveGroupMemberships.ps1

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,17 @@ begin {
148148
}
149149

150150
$CurrentProgressPreference = Get-Variable -Name ProgressPreference -ValueOnly
151-
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' -Scope Global -Force -ErrorAction SilentlyContinue
152-
# Check if the global catalog server is available on the specified port.
153-
if (-not (Test-NetConnection -ComputerName $Server -Port $Port -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
154-
if (-not (Test-NetConnection -ComputerName $Server -Port $AltPort -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
155-
throw "Unable to connect to the global catalog server '$Server' on port '$Port' or '$AltPort.'"
151+
try {
152+
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' -Scope Global -Force -ErrorAction SilentlyContinue
153+
# Check if the global catalog server is available on the specified port.
154+
if (-not (Test-NetConnection -ComputerName $Server -Port $Port -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
155+
if (-not (Test-NetConnection -ComputerName $Server -Port $AltPort -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
156+
throw "Unable to connect to the global catalog server '$Server' on port '$Port' or '$AltPort.'"
157+
}
156158
}
159+
} finally {
160+
Set-Variable -Name ProgressPreference -Value $CurrentProgressPreference -Scope Global -Force -ErrorAction SilentlyContinue
157161
}
158-
Set-Variable -Name ProgressPreference -Value $CurrentProgressPreference -Scope Global -Force -ErrorAction SilentlyContinue
159162
}
160163

161164
process {

Active Directory/Get-ADObjectFromPipeline.ps1

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ function Get-ADObjectFromPipeline {
1515

1616
begin {
1717
Import-Module ActiveDirectory
18-
$GlobalCatalog = Get-ADDomainController -Discover -Service GlobalCatalog
1918
}
2019

2120
process {
@@ -36,25 +35,15 @@ function Get-ADObjectFromPipeline {
3635
switch ($IdentityType) {
3736
'user' {
3837
# Not Complete
39-
$User = Get-ADUser -Identity $Identity -Properties PrimaryGroup,SidHistory
38+
Get-ADUser -Identity $Identity -Properties PrimaryGroup,SidHistory
4039
}
4140
'computer' {
4241
# Not Complete
43-
$Computer = Get-ADComputer -Identity $Identity -Properties PrimaryGroup,SidHistory
42+
Get-ADComputer -Identity $Identity -Properties PrimaryGroup,SidHistory
4443
}
4544
Default {
4645
Write-Error "Identity type not supported."
4746
}
4847
}
4948
}
50-
51-
end {
52-
# Do something and/or return the resulting object to the pipeline.
53-
if ($User) {
54-
$User
55-
}
56-
if ($Computer) {
57-
$Computer
58-
}
59-
}
6049
}

Active Directory/Get-ADUserTransitiveGroupMembership.ps1

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,17 @@ function Get-ADUserTransitiveGroupMembership {
5757
}
5858

5959
$CurrentProgressPreference = Get-Variable -Name ProgressPreference -ValueOnly
60-
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' -Force -Scope Global -ErrorAction SilentlyContinue
61-
# Check if the global catalog server is available on the specified port.
62-
if (-not (Test-NetConnection -ComputerName $Server -Port $Port -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
63-
if (-not (Test-NetConnection -ComputerName $Server -Port $AltPort -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
64-
throw "Unable to connect to the global catalog server '$Server' on port '$Port' or '$AltPort.'"
60+
try {
61+
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' -Force -Scope Global -ErrorAction SilentlyContinue
62+
# Check if the global catalog server is available on the specified port.
63+
if (-not (Test-NetConnection -ComputerName $Server -Port $Port -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
64+
if (-not (Test-NetConnection -ComputerName $Server -Port $AltPort -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
65+
throw "Unable to connect to the global catalog server '$Server' on port '$Port' or '$AltPort.'"
66+
}
6567
}
68+
} finally {
69+
Set-Variable -Name ProgressPreference -Value $CurrentProgressPreference -Force -Scope Global -ErrorAction SilentlyContinue
6670
}
67-
Set-Variable -Name ProgressPreference -Value $CurrentProgressPreference -Force -Scope Global -ErrorAction SilentlyContinue
6871
}
6972

7073
process {
Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1-
Get-ADComputer -SearchBase 'OU=Member Servers,DC=DOMAINNAME,DC=org' `
2-
-Properties Name, ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime -Filter { Name -notlike '*xen*' } | `
3-
Select-Object Name, ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime | Sort-Object Name | Out-GridView
1+
function Get-LAPSPassword {
2+
<#
3+
.SYNOPSIS
4+
Gets LAPS password metadata for computers in an Active Directory search base.
5+
6+
.DESCRIPTION
7+
Returns computer names and LAPS password expiration times by default. Use IncludePassword only when the caller
8+
has a secure process for handling plaintext local administrator passwords.
9+
10+
.PARAMETER SearchBase
11+
The distinguished name of the organizational unit or container to search.
12+
13+
.PARAMETER IncludePassword
14+
Includes the plaintext ms-Mcs-AdmPwd value in the output.
15+
16+
.EXAMPLE
17+
Get-LAPSPassword -SearchBase 'OU=Member Servers,DC=example,DC=com'
18+
19+
.OUTPUTS
20+
PSCustomObject
21+
#>
22+
[CmdletBinding()]
23+
[OutputType([PSCustomObject])]
24+
param (
25+
[Parameter(Mandatory)]
26+
[ValidateNotNullOrEmpty()]
27+
[string]
28+
$SearchBase,
29+
30+
[Parameter()]
31+
[switch]
32+
$IncludePassword
33+
)
34+
35+
$Properties = @('Name', 'ms-Mcs-AdmPwdExpirationTime')
36+
if ($IncludePassword) {
37+
Write-Warning 'Plaintext LAPS passwords will be included in the output. Handle the results securely.'
38+
$Properties += 'ms-Mcs-AdmPwd'
39+
}
40+
41+
Get-ADComputer -SearchBase $SearchBase -Properties $Properties -Filter { Name -notlike '*xen*' } |
42+
Sort-Object -Property Name |
43+
Select-Object -Property Name,
44+
@{ Name = 'Password'; Expression = { if ($IncludePassword) { $_.'ms-Mcs-AdmPwd' } else { '<redacted>' } } },
45+
@{ Name = 'PasswordExpirationTime'; Expression = { $_.'ms-Mcs-AdmPwdExpirationTime' } }
46+
}

Active Directory/Set DNS Server Zone Settings via Registry.ps1

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@
2727
those changes to be read and take effect.
2828
#>
2929

30-
# Prevent accidental running of this script until you've read the warning above:
31-
break
32-
3330
if ($session) { Remove-PSSession $session }
3431

3532
#Specify a list of DNS servers manually, or just get a list of all domain controllers in the domain.
@@ -39,31 +36,31 @@ $creds = Get-Credential
3936
#Loop through each server in the list, opening a PowerShell remoting session, then show the name and status of the session. Skips (continue) to the next server if a connection fails.
4037
foreach ($srv in $servers) {
4138
$server = $srv.Hostname
42-
$session = New-PSSession -ComputerName $server -Name $server -Credential $creds
39+
$session = $null
4340
Try {
4441
Write-Host "Connecting to $server... " -ForegroundColor Green -NoNewline
45-
Enter-PSSession $session
46-
} Catch {
47-
Write-Host "Failed to enter the PSSession for $server. Skipping." -ForegroundColor DarkYellow
48-
Continue
49-
}
50-
Write-Output $session.State
42+
$session = New-PSSession -ComputerName $server -Name $server -Credential $creds -ErrorAction Stop
43+
Write-Output $session.State
5144

52-
$zones = Get-ChildItem -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\DNS Server\Zones\'
45+
Invoke-Command -Session $session -ScriptBlock {
46+
$zones = Get-ChildItem -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\DNS Server\Zones\'
5347

54-
foreach ($zone in $zones) {
55-
Write-Host "`n`nName: $((Get-ItemProperty -PSPath $zone.PSPath).PSChildName)" -NoNewline -ForegroundColor Yellow
56-
Write-Host "`nSecondaryServers: $((Get-ItemProperty -PSPath $zone.PSPath).SecondaryServers)" -NoNewline
57-
Write-Host "`nSecureSecondaries: $((Get-ItemProperty -PSPath $zone.PSPath).SecureSecondaries) `n" -NoNewline
48+
foreach ($zone in $zones) {
49+
Write-Host "`n`nName: $((Get-ItemProperty -PSPath $zone.PSPath).PSChildName)" -NoNewline -ForegroundColor Yellow
50+
Write-Host "`nSecondaryServers: $((Get-ItemProperty -PSPath $zone.PSPath).SecondaryServers)" -NoNewline
51+
Write-Host "`nSecureSecondaries: $((Get-ItemProperty -PSPath $zone.PSPath).SecureSecondaries) `n" -NoNewline
5852

59-
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecondaryServers" -Value "" -Whatif
60-
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecureSecondaries" -Value "3" -Whatif
53+
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecondaryServers" -Value "" -WhatIf
54+
#Set-ItemProperty -PSPath $zone.PSPath -Name "SecureSecondaries" -Value "3" -WhatIf
55+
}
56+
}
57+
} Catch {
58+
Write-Host "Failed to enter the PSSession for $server. Skipping." -ForegroundColor DarkYellow
59+
Continue
60+
} Finally {
61+
if ($session) {
62+
Remove-PSSession $session
63+
Write-Host "$server session removed. `n`n" -NoNewline
64+
}
6165
}
62-
63-
64-
#Cleanup and then show the current PSSession state.
65-
if ($session) { Exit-PSSession }
66-
if ($session) { Remove-PSSession $session }
67-
Write-Host "$($session.ComputerName) $($session.State) `n`n" -NoNewline
68-
6966
}

DDI/Get Hostnames from CSV IP Addresses.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ $IPAddressList | foreach-object {
1010
$_.Hostname = ([System.Net.Dns]::GetHostEntry($ip)).HostName
1111
}
1212
catch {
13-
Write-Error $_ #.Exception.Message.Split(':')[1]
13+
Write-Error -ErrorRecord $_ #.Exception.Message.Split(':')[1]
1414
}
1515
}
1616
# Write the data back to the CSV with the hostnames added.

0 commit comments

Comments
 (0)