Have you ever woken up at 2:33 am to the phone ringing off the hook because some service is not longer running and it must be fixed right now? And this service not running is because someone reset the password on a service account last week? I’ve seen this scenario play out way more than it ever should. Let’s nip that problem of service accounts running wild right away.
<# .SYNOPSIS Checks all servers available in the domain for services running under service accounts. .DESCRIPTION Find-AllServiceAccounts grabs a list of all servers from the current domain and uses WMI calls to retrieve a list of services from the servers. It then loops through the services checking for service accounts and writes any service accounts found to a CSV specifically for that server. .NOTES You will be prompted for credentials when first running this. #> Import-Module ActiveDirectory # Default system accounts to exclude $ExcludedServices = "NT AUTHORITY\LocalService", "LocalSystem", "NT AUTHORITY\NETWORK SERVICE", "NT AUTHORITY\NetworkService" # Will pop up a prompt to provide credentials for making WMI calls # to the remote systems $Credentials = Get-Credential # Uses the LDAP search results for computers $HostList = Get-ADObject -SearchBase (Get-ADRootDSE).defaultNamingContext -LDAPFilter "(&(objectCategory=computer)(|(operatingSystem=Windows Server*)(operatingSystem=Windows 2000 Server)))" -Properties Name $HostName = Get-Content env:computername # Pass a service name in and check to see if it matches the excluded # service accounts that you've preconfigured function Check-ServiceName($ThisServiceName) { <# .SYNOPSIS Check-ServiceName verifies if a service is not a default service account .DESCRIPTION Check-ServiceName checks the service account for the specified service against the list of excluded services from the $ExcludedServices variable. Returns $true or $false. .PARAMETER ThisServiceName The service account to be checked against. #> foreach($ExcludedName in $ExcludedServices) { if($ThisServiceName -eq $ExcludedName.ToLower()) { return $true } } return $false } [array]$BadHostList = $null # Our main loop, iterates through each system listed in # the file and pulls all of their services foreach($HostServer in $HostList) { # Grab the list of services from the system if ($HostServer.Name -ne $HostName) { $ServiceList = get-WMIObject -Class win32_service -ComputerName $HostServer.name -Credential $Credentials -Property name,startname } # If it is the localhost then we need to exclude the credentials parameter else { $ServiceList = get-WMIObject -Class win32_service -ComputerName $HostServer.name -Property name,startname } # If the host could be contacted, loop through and check each service if($ServiceList) { [array]$CSVArray = $null foreach($ThisService in $ServiceList) { $CheckResult = Check-ServiceName($ThisService.StartName.ToLower()) if ($CheckResult -eq $false) { Write-Host "Service: " $ThisService.name Write-Host "Account: " $ThisService.StartName $CSVArray += ,$ThisService | select Name,StartName } } if ($CSVArray.count -gt 0) { Write-Host "Saving .csv for $HostServer" Write-Host "" $CSVArray | Export-CSV "$HostServer.csv" $CSVCount++ } } # The host could not be contacted, note it down else { Write-Host "$($HostServer.name) is unreachable." $BadHostList += $HostServer } } if($CSVCount -gt 1) { Write-Host "Done, wrote out $($CSVCount) .csv files." } elseif($CSVCount -eq 1) { Write-Host "Done, wrote out $($CSVCount) .csv file." } else { Write-Host "No .csv files written out, no service accounts found." } if($BadHostList) { foreach($TargetHost in $BadHostList) { Write-Host "$($TargetHost.Name) at $($TargetHost.DistinguishedName) was unreachable." } }
What this does for you is that it runs through all of your servers (assuming they will respond to WMI queries, you’ll want to check your firewall policies) and dumps out a CSV for any server with service accounts reporting what services are using service accounts and which service accounts those are. This will save you much frustration in tracking down who will be impacted by a service account password reset, security audits, password reset frenzies and just plain documentation.
Speaking of security audits and password resets, in an upcoming post I’ll show you how to easily update all of your service account passwords so that you can spend the rest of the day playing Animal Crossing rather than remoting from server to server to server …
Did this post help you out? Do you have any questions or a specific topic you’d like me to delve into? Just let me know, thanks!