Skip to content

Instantly share code, notes, and snippets.

@Rugby-Ball
Last active February 14, 2024 22:50
Show Gist options
  • Select an option

  • Save Rugby-Ball/0774f472e882ff965178f20ad390ad95 to your computer and use it in GitHub Desktop.

Select an option

Save Rugby-Ball/0774f472e882ff965178f20ad390ad95 to your computer and use it in GitHub Desktop.
Pulls a list of AWS Windows servers, and then scans each for the date of last patch done one server. Exports to a CSV file. #AWS #Public #Inventory #Security #Utility #Audit #Windows #Patching
#list-all-windows-servers-last-date-patched.ps1
#Use to pull a list of running servers (Windows and/or Linux depending on what you select in $Filters) removing any that are not in AD and are associated to WORKGROUP.
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
$stopwatch.Start()
$stopWatch2 = [System.Diagnostics.Stopwatch]::StartNew()
$stopwatch2.Start()
Import-Module -name AWSPowershell
$Servers = @()
# Get the Running EC2 Instances managed by SSM
$Filters = @(@{ Key = 'PingStatus'; values = 'Online' }; @{ key = "PlatformTypes"; values = ("Windows") }; @{ Key = "ResourceType"; values = "EC2Instance" })
Get-EC2Region -RegionToCall us-east-1 <# -RegionToCall used because of https://github.com/aws/aws-tools-for-powershell/issues/46 #> | Foreach-Object {
$region = $_.RegionName
$Servers += Get-SSMInstanceInformation -Region $Region -Filter $Filters | Select-Object @{Name = 'Region'; Expression = {$Region} },InstanceId,ComputerName, @{Name = 'EC2Name'; Expression ={ ((((Get-EC2Instance -region $region -InstanceId $_.InstanceID ).Instances).tag) | Where-Object {($_.Key -eq 'Name')} | select-object @{name="EC2Name"; expression={$_.Value}}).EC2Name } }, IPAddress, PlatformType, PlatformName, PlatformVersion, LastPingDateTime
}
$serverNames = $Servers | Where-Object { ($_.computername -NotLike "*.workgroup") } | Sort-Object region, ComputerName , EC2Name, IPAddress, @{expression='PlatformType';descending=$true}, PlatformVersion
# awsdb-b1.MRIRDP.com
$stopwatch2.Stop()
$time2 = $stopwatch2.Elapsed
Write-Host "First part of Script finished on $(Get-Date -f "MM-dd-yyyy hh:mm tt"), Elapsed time to run script (HH:MM:SS.MS): $Time2" -ForegroundColor Black -BackgroundColor Yellow
# Initialize an empty array to store patch information
$patchInfo = @()
# Loop through each server
foreach ($server in $serverNames) {
try {
$PatchSchedule = (get-ec2tag -region $server.Region -filter @{Name = "resource-id"; Values= $server.InstanceId }, @{Name="key";Values="patch"}).Value
# Get the installed hotfixes for the server
$lastPatch = Get-HotFix -ComputerName $server.ComputerName | Sort-Object InstalledOn -Descending | Select-Object -First 1
# Select relevant properties (you can customize this as needed)
$patchInfo += $lastPatch | Select-Object @{n="Host-Name";e= {$server.ComputerName } }, @{n="EC2-Name";e= {$server.EC2Name} }, @{n="Region";e={$server.region} }, @{n="Platform";e={$server.PlatformName} }, HotfixID, InstalledOn,@{n="Patch-Tag"; e={$PatchSchedule}} , @{n="Errors";e={""} }
} catch {
$patchInfo += $lastPatch | Select-Object @{n="Host-Name";e= {$server.ComputerName } }, @{n="EC2-Name";e= {$server.EC2Name} }, @{n="Region";e={$server.region} }, @{n="Platform";e={$server.PlatformName} }, @{n="HotfixID";e={""} }, @{n="InstalledOn";e={""} },@{n="Patch-Tag"; e={$PatchSchedule}} ,@{n="Errors";e= {$Error[0]} }
Write-Host "Error connecting to server $($server.ComputerName) -:- $_"
}
}
# Export the patch information to a CSV file
$patchInfo | Export-Csv -Path "C:\temp\Last-Patch-List.csv" -NoTypeInformation
Write-Host "Patch information exported to C:\temp\Last-Patch-List.csv"
$stopwatch.Stop()
$time = $stopwatch.Elapsed
Write-Host "Script finished on $(Get-Date -f "MM-dd-yyyy hh:mm tt"), Elapsed time to run script (HH:MM:SS.MS): $Time" -ForegroundColor Red -BackgroundColor Yellow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment