Skip to content

Instantly share code, notes, and snippets.

@Rugby-Ball
Last active July 7, 2023 14:28
Show Gist options
  • Select an option

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

Select an option

Save Rugby-Ball/8d9f6f467df3cf60eda655ae8ecd9e47 to your computer and use it in GitHub Desktop.
Do a search/inventory for a specific domains SSL across all Running Domain joined IIS servers. Will also pull in ALL ssl certs installed on all server for #Powershell #Inventory #Utility #WebServer #SSL_Certificate #Public # SSL # IIS
#ssl-cert-scan-inventory-IIS-servers.ps1
<#
Description: Pull ALL ssl certs installed on all Windows servers for a full inventory of installed SSL Certificates.
Written: Ed Walsh
PowerShell.Core tested: No
Version: 2.1
Create Date: 5/15/2021
Revised Date: 7/7/2023
#>
Import-Module -name AWSPowershell
$timestamp = get-date -format yyyyMMddHHmmss
$subfolder = if (($PSVersionTable.PSEdition) -eq "Core") { if ( $True -eq $iswindows ) { "\Documents\" } Else { "" } } Else {"\Documents\"}
$mydocuments = $home + $subfolder
$fileName = "Installed-Windows-SSL-Certificate-Inventory-"+ [string]$timestamp + ".csv"
$filePath = Join-Path $mydocuments $fileName
$ErrorActionPreference = 'Stop'
$Array = @()
##-----------------------------------------------------------------------------------------##
## Chose which option you want to use to pull the variable $Servers ##
##-----------------------------------------------------------------------------------------##
#
## This will only get EC2's that are Windows and Running, and have a WEB or WB in the EC2 Tag 'Name'
#$Servers = ((((Get-EC2Instance -region $region -Filter @( @{name = 'instance-state-name'; values = 'running' }; , @{name = 'platform'; values = "windows" }) ).Instances).tag) | Where-Object {($_.Key -eq 'Name' -and $_.Value -Match 'WEB') -or ($_.Key -eq 'Name' -and $_.Value -Match 'WB')} | select-object @{name="Hostname"; expression={$_.Value + ".mrirdp.com"}}).hostname
## Use if you want ALL running Windows EC2's. This can take some time to run. Be patient.
#$Servers = ((((Get-EC2Instance -region $region -Filter @( @{name = 'instance-state-name'; values = 'running' }; , @{name = 'platform'; values = "windows" }) ).Instances).tag) |Where-Object {($_.Key -eq 'Name')} | select-object @{name="Hostname"; expression={$_.Value + ".mrirdp.com"}}).hostname
## This gets the servers Hostname using SSM
$Servers = @()
# Get the Running EC2 Instances managed by SSM
$Filters = @(@{ Key = 'PingStatus'; values = 'Online' }; @{ key = "PlatformTypes"; values = (<#"Linux",#> "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 @{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
}
# Remove WORKGROUP servers
$Servers = $Servers | where computername -NotLike "*.workgroup"
##-------------------------------------------------------------------##
# Looping each server
foreach($Server in $Servers)
{
Write-Host Processing $Server.ComputerName -ForegroundColor yellow
Try
{
# Checking local DNS for hostname of a server provided in variable. If not found throw an error.
#$hostname = ([System.Net.Dns]::GetHostByName("$Server")).hostname
$hostname = $Server.ComputerName
# Querying for certificates on remote server.
$Certs = Invoke-Command $Server.ComputerName -ScriptBlock{ Get-ChildItem Cert:\LocalMachine\* -Recurse | where-object {($_.PSParentPath -eq "Microsoft.PowerShell.Security\Certificate::LocalMachine\My") -or ($_.PSParentPath -eq "Microsoft.PowerShell.Security\Certificate::LocalMachine\webhosting") } }
If ($certs -eq $Null) {$certs = "No certs"}
}
Catch
{
$errormsg = $_.Exception.Message
$hostnamenotmatch = "*No such host is known*"
$tagname = $Server.ComputerName #$Server.Substring(0,$server.Length-11)
if ($errormsg -like $hostnamenotmatch) {Write-Host "The EC2 Name Tag: " -f Magenta -nonewline; Write-Host $tagname -f white -nonewline; Write-Host " is not found as a hostname in the Local DNS." -ForegroundColor Magenta} Else {$errormsg}
Continue
}
If($hostname -and $Certs)
{
Foreach($Cert in $Certs)
{
#RegEx out the URL from the Subject field, if blank return blank
$Subject = if (($cert.Subject)) {($cert.Subject) -replace "(CN=)(.*?),.*",'$2'} else {($cert.Subject)}
#Is $Subject a URL
$A_URL = if ($Subject -match " " -or $Subject -like "CN=*" -or $Subject -eq "" -or $Subject -eq $Null ) {$False} Else {$True}
# Adding certificate properties and server name to object
#$Object = New-Object PSObject
$Object = New-Object pscustomobject
$Object | Add-Member Noteproperty "Region" -Value $Server.region
$Object | Add-Member Noteproperty "InstanceID" -Value $Server.InstanceID
$Object | Add-Member Noteproperty "EC2_name" -Value $Server.ec2name
$Object | Add-Member Noteproperty "Server_HostName" -Value $hostname
#Below using -join, avoids the issue of returning System.Object[] in a CSV file.
$Object | Add-Member Noteproperty "Certificate_name" -Value (@($cert.dnsnamelist.punycode) -join ',') #This is original way to do it # $cert.dnsnamelist.punycode
$Object | Add-Member Noteproperty "Certificate_issuer" -Value $cert.issuer
$Object | Add-Member Noteproperty "Certificate_expiration date" -Value $cert.notafter
$Object | Add-Member Noteproperty "Certificate_thumbprint" -Value $cert.thumbprint
$Object | Add-Member Noteproperty "Certificate_Location" -Value $cert.PSParentPath
$Object | Add-Member Noteproperty "Certificate_Subject" -Value $Subject
$Object | Add-Member Noteproperty "Certificate_Subject_A_URL" -Value $A_URL
# Adding object to an array
$Array += $Object
}
}
Else
{
Write-Warning "Something went wrong on $Server.ComputerName"
}
}
If($Array)
{
## Display searched certificate.
# $array | Where-Object {($_.Certificate_Subject_a_URL -eq $True)} | Sort-Object $_.Certificate_Subject
## To export to CSV
#This adds a filter to check if a URL, and dumps the list of all SSL certs on all Windows Webservers on the domain.
$array | Where-Object {($_.Certificate_Subject_a_URL -eq $True)} | Sort-Object $_.Certificate_Subject | Export-Csv -Path $filePath -Force -NoTypeInformation
}
Write-Output "Exported to: $filePath"
Write-Output "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|||||||////////////////////////////////////"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment