Password file audit optimization in PowerShell

Theoretically all administrators regularly clean up the unused accounts form their environment, so an audit is not problem for them. What if I have more than 3000 servers? It is a huge problem for me, without automation. So in this article you can read about joined loop optimization, because sometimes the joined for loop is time-consuming. The fact is true – many a little makes a mickle.

The problem

We have a file, named names_to_keep, filled in active accounts that must need to remain in the new password files. And we have more than 3000 password file, named passwd, copied from each server. We need to compare all password file with the active accounts file to query the needed accounts.

Here is an example passwd file:

And an active accounts (names_to_keep) file:

The solution

If we use joined for loop in the script, it process all lines, without checking needed or not. Here is my example joined loop script.

$datebegin = date

$keepfile = (Get-Content "c:\Tmp\audit\names_to_keep") 
$pwdfile = (Get-Content c:\Tmp\audit\passwd) 

$pwdfrom = 0
$pwdto = $pwdfile.Count
$keepfrom = 0
$keepto = $keepfile.Count

For ( $i = $pwdfrom; $i -lt $pwdto; $i++ ) {
	For ( $j = $keepfrom; $j -lt $keepto; $j++ ) {
		If (($pwdfile[$i].Split(":"))[0] -eq $keepfile[$j])
			{
			Write-Host $pwdfile[$i]
			}
		}
	}
	
Write-Host "Script finished"
$datefinish = date
$delta = $datefinish - $datebegin
Write-Host $delta

Optimization

First of all I need to get rid of the joined for loop, because the while loop fulfill my requirements. Here is my optimized script, that I describe it later.

$datebegin = date

$keepfile = (Get-Content "c:\Tmp\audit\names_to_keep") |Sort-Object
$pwdfile = (Get-Content c:\Tmp\audit\passwd) |Sort-Object

$pwdfrom = 0
$pwdto = $pwdfile.Count
$keepfrom = 0
$keepto = $keepfile.Count
$found = 0    #pointer for the last matching position

While ($pwdfrom -lt $pwdto)
	{
	If ($found -ne 0) {$keepfrom = $found} Else {$keepfrom = 0}
	While ($keepfrom -lt $keepto)
		{
		If (($pwdfile[$pwdfrom].Split(":"))[0] -eq $keepfile[$keepfrom])
			{
			Write-Host $pwdfile[$pwdfrom]
			$pwdfrom++               #mowe to the next item
			$found = $keepfrom + 1   #last mach position
			}
		$keepfrom++
		}
	#if the inner loop stops, stop the outer loop
	If ($keepfrom -eq $keepto)
		{$pwdfrom = $pwdto}
	$pwdfrom++
	}	
	
Write-Host "Script finished"
$datefinish = date
$delta = $datefinish - $datebegin
Write-Host $delta

Why this script more than a joined for loop? Let me explain:

Basically the pwdfile and the keepfile are not sorted, so we need to sort them to easily calculate with it.

Using while loop we can easily manipulate the pointers inside the loops. We can define rules depending on the problem. I defined these rules:

–          I start the query from top to bottom,

–          If a pair of username matches, then next time the inner loop will begin after the last match,

–          If a pair of username matches, then the outer loop pointer step one forward,

–          If the pointer of the inner loop reaches the maximum (no more names need to compare), then the outer loop will be stopped.

The results

And what is the aim of the optimization? The running time is important, so I significantly reeducate it by these tricks. Here are my running times. The audit_long script is the joined for loop version, and the audit script is the optimized.

Summary

As you can see, the optimization is important for us, because we can save time (money) with it. The for loop go from the beginning through the ending, but sometimes it is time-consuming. The well-defined rules can help us to choose the right loop form.

That’s all folks!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s