Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Created May 27, 2016 23:12
Show Gist options
  • Save JustinGrote/24ba4b4711592b8387fe4d527c529b0d to your computer and use it in GitHub Desktop.
Save JustinGrote/24ba4b4711592b8387fe4d527c529b0d to your computer and use it in GitHub Desktop.
Get-AllLocalGroupAdmins - Get Active Computers in AD and return the local Administrator group membership. Report as Excel.
#requires -version 5.0
<#
.SYNOPSIS
Finds active computers in AD and collects a list of their group memberships
#>
param (
#Path to output the resulting Excel Report
[String]$Path = "LocalAdminGroupReport-$(get-date -format yyyyhhmmss).xlsx",
#Use fancy CIM Method. Only works if winrm remote management is enabled
[Switch]$CIM,
#Get all the members of groups and include them in the results rather than the group names
[Switch]$ExpandGroups
)
#region Prerequisites
$PrerequisiteModules = "poshrsjob","importexcel"
$CurrentUserModulePath = "$home\Documents\WindowsPowerShell\Modules\"
install-module $PrerequisiteModules -scope currentuser -Confirm:$false -ErrorAction stop
$PrerequisiteModules | foreach {
import-module "$CurrentUserModulePath\$PSItem" -erroraction stop
}
#endregion Prerequisites
#region Includes
Function Get-RemoteGroupMembership
{
<#
.SYNOPSIS
Gather list of all assigned users in all local groups on a computer.
.DESCRIPTION
Gather list of all assigned users in all local groups on a computer.
.PARAMETER ComputerName
Specifies the target computer for data query.
.PARAMETER IncludeEmptyGroups
Include local groups without any user membership.
.PARAMETER ThrottleLimit
Specifies the maximum number of systems to inventory simultaneously
.PARAMETER Timeout
Specifies the maximum time in second command can run in background before terminating this thread.
.PARAMETER ShowProgress
Show progress bar information
.EXAMPLE
PS > (Get-RemoteGroupMembership -verbose).GroupMembership
<output>
Description
-----------
List all group membership of the local machine.
.NOTES
Author: Zachary Loeber
Site: http://www.the-little-things.net/
Requires: Powershell 2.0
Version History
1.0.0 - 09/09/2013
- Initial release
#>
[CmdletBinding()]
param
(
[string]
$ComputerName,
[Parameter(HelpMessage="Include empty groups in results")]
[switch]
$IncludeEmptyGroups,
[Parameter(HelpMessage="Set this if you want the function to prompt for alternate credentials")]
[switch]
$PromptForCredential,
[Parameter(HelpMessage="Set this if you want to provide your own alternate credentials")]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
PROCESS
{
# This is the actual code called for each computer
Write-Verbose -Message ("Local Group Membership: WMI Query to $computername")
$WMIHast = @{
ComputerName = $ComputerName
ErrorAction = 'Stop'
}
# General variables
$GroupMembership = @()
$PSDateTime = Get-Date
# Modify this variable to change your default set of display properties
$defaultProperties = @('ComputerName','GroupMembership')
$wmi_groups = Get-WmiObject @WMIHast -Class win32_group -filter "SID = 'S-1-5-32-544'"
foreach ($group in $wmi_groups)
{
$Query = "SELECT * FROM Win32_GroupUser WHERE GroupComponent = `"Win32_Group.Domain='$($group.domain)',Name='$($group.name)'`""
$wmi_users = Get-WmiObject @WMIHast -query $Query -Verbose
if (($wmi_users -eq $null) -and ($IncludeEmptyGroups))
{
[PSCustomObject][Ordered]@{
'Computername' = $ComputerName
'Group' = $group.Name
'GroupMember' = ''
'MemberType' = ''
}
}
else
{
foreach ($user in $wmi_users.partcomponent)
{
if ($user -match 'Win32_UserAccount')
{
$Type = 'User'
}
elseif ($user -match 'Win32_Group')
{
$Type = 'Group'
}
elseif ($user -match 'Win32_SystemAccount')
{
$Type = 'SystemAccount'
}
else
{
$Type = 'Other'
}
#Output the result
[pscustomobject][ordered]@{
'ComputerName' = $ComputerName
'Group' = $group.Name
'GroupMember' = (($user.replace("Domain="," , ").replace(",Name=","\").replace("\\",",").replace('"','').split(","))[2]).trim()
'Type' = $Type
}
}
}
}
}
}
#endregion Includes
#region Main
$activeServerList = get-adcomputer -Properties lastlogondate -filter {operatingsystem -like "*Server*" -and enabled -eq $true} |
where lastlogondate -gt (get-date).adddays(-30) |
sort lastlogondate -Descending |
select -expandproperty dnshostname
$batchID = "GetRemoteGroups-" + $(new-guid).guid
$localGroupMemberships = $activeServerList | start-rsjob -FunctionsToLoad "Get-RemoteGroupMembership" -batch $batchID {
$ComputerName = $PSItem
write-verbose "Getting Administrator Group Members of $ComputerName"
if ($USING:CIM) {
try {
get-ciminstance -computername $ComputerName -classname win32_group -filter "Name = 'administrators'" -ErrorAction Stop |
get-cimassociatedinstance -association win32_groupuser -ErrorAction Stop
} catch {
$PSItem
#write-warning "$ComputerName`: Failed to collect local admin information. Error: $PSItem"
}
} else {
Get-RemoteGroupMembership -ComputerName $ComputerName | where
} #else
} |
wait-rsjob -ShowProgress |
receive-rsjob
$localGroupMemberships | export-excel -path $Path -WorkSheetname "Local Admins" -TableName "LocalAdmins"
remove-rsjob -batch $batchID -force
#Get the SID of the group using .NET function
$localGroupMemberships | where type -match "Group" | select -ExpandProperty GroupMember -unique | foreach {
$groupDomain = ($PSItem -split '\\')[0]
$groupName = ($PSItem -split '\\')[1]
$groupSID = (new-object System.Security.Principal.NTAccount($groupDomain, $groupName)).translate([System.Security.Principal.SecurityIdentifier]).value
#Generate the group membership entries
(get-adgroupmember $groupSID -recursive -ErrorAction stop) | foreach {
[PSCustomObject]@{
Domain = $groupDomain
Name = $groupName
SID = $groupSID
Member = $PSItem.samaccountname
MemberDisplayName = $PSItem.name
}
}
} | export-excel -path $Path -WorkSheetname "AD Groups" -TableName "ADGroups"
#endregion Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment