Skip to content

Instantly share code, notes, and snippets.

@andreafortuna
Created November 7, 2019 14:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save andreafortuna/5c5489c1cc2f86899c8a10d42a025a5b to your computer and use it in GitHub Desktop.
Save andreafortuna/5c5489c1cc2f86899c8a10d42a025a5b to your computer and use it in GitHub Desktop.
Powershell script to read service configuration from all Windows servers in the current domain and generate report listing all domain accounts used as service logon account
<#
Service account report scrip that reads service configuration from
all Windows servers in the current domain and generate a report listing all
domain accounts used as service logon account.
By Andrea Fortuna (andrea@andreafortuna.org)
*** Based on "report-service-accounts.ps1" by Gleb Yourchenko (fnugry@null.net) ***
#>
$reportFile = ".\report.html"
$maxThreads = 10
$currentDomain = $env:USERDOMAIN.ToUpper()
$serviceAccounts = @{}
[string[]]$warnings = @()
$readServiceAccounts = {
# Retrieve service list form a remote machine
param( $hostname )
if ( Test-Connection -ComputerName $hostname -Count 3 -Quiet ){
try {
$serviceList = @( gwmi -Class Win32_Service -ComputerName $hostname -Property Name,StartName,SystemName -ErrorAction Stop )
$serviceList
}
catch{
"Failed to retrieve data from $hostname : $($_.toString())"
}
}
else{
"$hostname is unreachable"
}
}
function processCompletedJobs(){
# reads service list from completed jobs,updates $serviceAccount table and removes completed job
$jobs = Get-Job -State Completed
foreach( $job in $jobs ) {
$data = Receive-Job $job
Remove-Job $job
if ( $data.GetType() -eq [Object[]] ){
$serviceList = $data | ? { $_.StartName.toUpper().StartsWith( $currentDomain )}
foreach( $service in $serviceList ){
$account = $service.StartName
$occurance = "`"$($service.Name)`" service on $($service.SystemName)"
if ( $script:serviceAccounts.Contains( $account ) ){
$script:serviceAccounts.Item($account) += $occurance
}
else {
$script:serviceAccounts.Add( $account, @( $occurance ) )
}
}
}
elseif ( $data.GetType() -eq [String] ) {
$script:warnings += $data
Write-warning $data
}
}
}
################# MAIN #########################
Import-Module ActiveDirectory
# read computer accounts from current domain
Write-Progress -Activity "Retrieving server list from domain" -Status "Processing..." -PercentComplete 0
$serverList = Get-ADComputer -Filter {OperatingSystem -like "Windows Server*"} -Properties DNSHostName, cn | ? { $_.enabled }
# start data retrieval job for each server in the list
# use up to $maxThreads threads
$count_servers = 0
foreach( $server in $serverList ){
Start-Job -ScriptBlock $readServiceAccounts -Name "read_$($server.cn)" -ArgumentList $server.dnshostname | Out-Null
++$count_servers
Write-Progress -Activity "Retrieving data from servers" -Status "Processing..." -PercentComplete ( $count_servers * 100 / $serverList.Count )
while ( ( Get-Job -State Running).count -ge $maxThreads ) { Start-Sleep -Seconds 3 }
processCompletedJobs
}
# process remaining jobs
Write-Progress -Activity "Retrieving data from servers" -Status "Waiting for background jobs to complete..." -PercentComplete 100
Wait-Job -State Running -Timeout 30 | Out-Null
Get-Job -State Running | Stop-Job
processCompletedJobs
# prepare data table for report
Write-Progress -Activity "Generating report" -Status "Please wait..." -PercentComplete 0
$accountTable = @()
foreach( $serviceAccount in $serviceAccounts.Keys ) {
foreach( $occurance in $serviceAccounts.item($serviceAccount) ){
$row = new-object psobject
Add-Member -InputObject $row -MemberType NoteProperty -Name "Account" -Value $serviceAccount
Add-Member -InputObject $row -MemberType NoteProperty -Name "Usage" -Value $occurance
$accountTable += $row
}
}
# create report
$report = "
<!DOCTYPE html>
<html>
<head>
<style>
TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;white-space:nowrap;}
TH{border-width: 1px;padding: 4px;border-style: solid;border-color: black}
TD{border-width: 1px;padding: 2px 10px;border-style: solid;border-color: black}
</style>
</head>
<body>
<H1>Service account report for $currentDomain domain</H1>
$($serverList.count) servers processed. Discovered $($serviceAccounts.count) service accounts.
<H2>Discovered service accounts</H2>
$( $accountTable | Sort Account | ConvertTo-Html Account, Usage -Fragment )
<H2>Warning messages</H2>
$( $warnings | % { "<p>$_</p>" } )
</body>
</html>"
Write-Progress -Activity "Generating report" -Status "Please wait..." -Completed
$report | Set-Content $reportFile -Force
Invoke-Expression $reportFile
@Thulasidasansubramani
Copy link

I have to collect service account details in our domain but how to use this script, any modifications we need to or what? Kindly help me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment