Advertisement
HorselessName

IIS Sites and Certificates Monitoring

Oct 11th, 2024 (edited)
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 13.02 KB | Source Code | 0 0
  1. function global:Write-Host() {} # Supress Write-Hosts Logs (Keep for Debugging).
  2.  
  3. # Ensure WebAdministration module is available and loaded
  4. function Ensure-WebAdministrationModule {
  5.     Write-Host "Checking if WebAdministration module is available..." -ForegroundColor Yellow
  6.     if (-not (Get-Module -ListAvailable -Name WebAdministration)) {
  7.         try {
  8.             Write-Host "WebAdministration module not found, attempting to import..." -ForegroundColor Yellow
  9.             Import-Module WebAdministration -WarningAction:SilentlyContinue
  10.             Write-Host "WebAdministration module successfully imported." -ForegroundColor Green
  11.         }
  12.         catch {
  13.             Write-Host "Failed to import WebAdministration module." -ForegroundColor Red
  14.             Exit 1  # Exit the script if the module cannot be imported
  15.         }
  16.     } else {
  17.         Write-Host "WebAdministration module is already available." -ForegroundColor Green
  18.     }
  19.  
  20.     if (-not (Get-Command -Name Get-Website -ErrorAction SilentlyContinue)) {
  21.         Write-Host "Get-Website cmdlet not available. Exiting..." -ForegroundColor Red
  22.         Exit 1  # Exit if the Get-Website cmdlet is not available
  23.     } else {
  24.         Write-Host "Get-Website cmdlet is available." -ForegroundColor Green
  25.     }
  26. }
  27.  
  28. # Get the bindings for a site using Get-WebBinding (for WebAdministration)
  29. function Get-SiteBindings {
  30.     param (
  31.         [string]$SiteName  # Name of the site for which we want bindings
  32.     )
  33.  
  34.     Write-Host "Fetching bindings for site: $SiteName" -ForegroundColor Cyan
  35.  
  36.     try {
  37.         # Use Get-WebBinding to fetch bindings for the site
  38.         $bindings = Get-WebBinding -Name $SiteName
  39.         if (-not $bindings) {
  40.             Write-Host "No bindings found for site: $SiteName" -ForegroundColor Red
  41.             return $null
  42.         }
  43.        
  44.         # Log retrieved bindings
  45.         $bindings | ForEach-Object {
  46.             Write-Host "Binding: Protocol=$($_.protocol), Info=$($_.bindingInformation)" -ForegroundColor Cyan
  47.         }
  48.  
  49.         return $bindings
  50.     }
  51.     catch {
  52.         Write-Host "Error fetching bindings for site: $SiteName. Exception: $_" -ForegroundColor Red
  53.         return $null
  54.     }
  55. }
  56.  
  57. # Process each binding for a site and apply filtering
  58. function Process-SiteBindings {
  59.     param (
  60.         [array]$bindings  # The full set of bindings for the current site
  61.     )
  62.  
  63.     Write-Host "`n[Process-SiteBindings] Processing site bindings..." -ForegroundColor Cyan
  64.     Write-Host "Bindings count: $($bindings.Count)" -ForegroundColor Cyan
  65.  
  66.     # Log the received bindings to see their structure
  67.     $bindings | ForEach-Object { Write-Host "Binding Object: $($_.ToString())" -ForegroundColor Cyan }
  68.  
  69.     # Case 1: Single binding
  70.     if ($bindings.Count -eq 1) {
  71.         Write-Host "Single binding detected." -ForegroundColor Cyan
  72.  
  73.         # Prepare the single binding as a PSCustomObject
  74.         $singleBinding = @(
  75.             [PSCustomObject]@{
  76.                 "Protocol"          = $bindings[0].protocol
  77.                 "BindingInformation" = $bindings[0].bindingInformation
  78.             }
  79.         )
  80.        
  81.         Write-Host "`nPrepared single binding: $($singleBinding | ConvertTo-Json -Compress)" -ForegroundColor Cyan
  82.         return Filter-SiteBindings -bindings $singleBinding
  83.     }
  84.  
  85.     # Case 2: Multiple bindings
  86.     elseif ($bindings.Count -gt 1) {
  87.         Write-Host "Multiple bindings detected. Applying filter..." -ForegroundColor Cyan
  88.         return Filter-SiteBindings -bindings $bindings
  89.     }
  90.  
  91.     # Case 3: No bindings or empty bindings
  92.     else {
  93.         Write-Host "No bindings found or bindings are empty." -ForegroundColor Red
  94.         return $null
  95.     }
  96. }
  97.  
  98. # Filter site bindings based on exclusion patterns
  99. function Filter-SiteBindings {
  100.     param (
  101.         [array]$bindings  # Input array of bindings
  102.     )
  103.  
  104.     Write-Host "`n[Filter-SiteBindings] Entering function with minimal filtering (BindingInformation length check)..." -ForegroundColor Blue
  105.  
  106.     if (-not $bindings) {
  107.         Write-Host "No bindings passed to filter. Exiting Filter-SiteBindings." -ForegroundColor Red
  108.         return $null
  109.     }
  110.  
  111.     # Log the received bindings for better clarity
  112.     $bindings | ForEach-Object {
  113.         Write-Host "`nReceived Binding: $($_.ToString())" -ForegroundColor Blue
  114.     }
  115.  
  116.     # Apply the exclusion filter based on BindingInformation length (<14 characters)
  117.     $filteredBindings = $bindings | Where-Object {
  118.         $_.BindingInformation -notmatch "^.{1,14}$"  # Exclude very short bindings (1 to 14 characters)
  119.     }
  120.  
  121.     # Log the filtered bindings
  122.     if ($filteredBindings) {
  123.         Write-Host "`nFiltered Bindings after applying BindingInformation length check:" -ForegroundColor Blue
  124.         $filteredBindings | ForEach-Object {
  125.             Write-Host "Filtered Binding: Protocol=$($_.protocol), BindingInformation=$($_.BindingInformation)" -ForegroundColor Blue
  126.         }
  127.     } else {
  128.         Write-Host "No bindings matched the filter criteria." -ForegroundColor Red
  129.     }
  130.  
  131.     # Return filtered bindings as PSCustomObject
  132.     $allBindings = $filteredBindings | ForEach-Object {
  133.         [PSCustomObject]@{
  134.             "Protocol" = $_.protocol
  135.             "BindingInformation" = $_.bindingInformation
  136.         }
  137.     }
  138.  
  139.     return $allBindings
  140. }
  141.  
  142. # Get the SSL certificate thumbprint for the given site's bindings
  143. function Get-SiteSSLCertificateDetails {
  144.     param (
  145.         [string]$SiteName  # Site for which we want to get SSL certificate details
  146.     )
  147.  
  148.     Write-Host "`nGetting SSL certificate thumbprint for site: $SiteName" -ForegroundColor Magenta
  149.     $bindings = Get-SiteBindings -SiteName $SiteName
  150.  
  151.     if (-not $bindings) {
  152.         Write-Host "No bindings found for the site: $SiteName" -ForegroundColor Red
  153.         return $null
  154.     }
  155.  
  156.     $certificateThumbprints = @()
  157.     foreach ($binding in $bindings) {
  158.         if ($binding.protocol -eq "https") {
  159.             # Safely retrieve the certificate hash from the binding
  160.             $thumbprint = $binding.certificateHash
  161.             Write-Host "Found certificate hash: $thumbprint" -ForegroundColor Magenta
  162.  
  163.             # Add the thumbprint to the list if it exists
  164.             if ($thumbprint) {
  165.                 $certificateThumbprints += $thumbprint
  166.             } else {
  167.                 Write-Host "No certificate hash found for this binding." -ForegroundColor Red
  168.             }
  169.         }
  170.     }
  171.  
  172.     # Log thumbprints found
  173.     if ($certificateThumbprints) {
  174.         Write-Host "Certificate thumbprints found for site $SiteName : $($certificateThumbprints -join ', ')" -ForegroundColor Magenta
  175.     } else {
  176.         Write-Host "No certificate thumbprints found for site $SiteName" -ForegroundColor Red
  177.     }
  178.  
  179.     return ($certificateThumbprints | Select-Object -Unique)
  180. }
  181.  
  182. # Retrieve certificate details from the LocalMachine\My store using the thumbprint
  183. function Get-SSLCertificate {
  184.     param (
  185.         [string]$Thumbprint
  186.     )
  187.  
  188.     Write-Host "`nRetrieving certificate for thumbprint: $Thumbprint" -ForegroundColor Yellow
  189.     $certificate = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq $Thumbprint }
  190.  
  191.     if ($certificate) {
  192.         Write-Host "Certificate found: $($certificate.Subject)" -ForegroundColor Yellow
  193.     } else {
  194.         Write-Host "No certificate found with thumbprint: $Thumbprint" -ForegroundColor Red
  195.     }
  196.  
  197.     return $certificate
  198. }
  199. # Function to clean up the JSON string
  200. function CleanUp-JsonString {
  201.     param (
  202.         [string]$jsonString
  203.     )
  204.     # Replace "\r\n" and any extra whitespace to clean up the JSON string
  205.     $cleanedJson = $jsonString -replace "\r\n", "" -replace "\s{2,}", ""
  206.     return $cleanedJson
  207. }
  208.  
  209. # Function to discover site certificates and return an array or object
  210. function Discover-SiteCertificates {
  211.     param (
  212.         [string]$SiteName  # The name of the site to get certificates for
  213.     )
  214.  
  215.     Write-Host "`nDiscovering certificates for site: $SiteName" -ForegroundColor Magenta
  216.  
  217.     # Attempt to get SSL certificate thumbprints for each binding
  218.     $thumbprints = Get-SiteSSLCertificateDetails -SiteName $SiteName
  219.  
  220.     # Initialize certificate information as an array (in case of multiple certificates)
  221.     $certificateInfo = @()
  222.  
  223.     # Check if thumbprints are found before retrieving certificate details
  224.     if ($thumbprints) {
  225.         Write-Host "`nThumbprints found for site. Starting to retrieve certificate details..." -ForegroundColor Magenta
  226.         Write-Host "Number of thumbprints: $($thumbprints.Count)" -ForegroundColor Magenta
  227.  
  228.         # Iterate through each thumbprint and attempt to retrieve the certificate
  229.         foreach ($thumbprint in $thumbprints) {
  230.             Write-Host "`nProcessing thumbprint: $thumbprint" -ForegroundColor Magenta
  231.  
  232.             # Call the function to get certificate details for the thumbprint
  233.             $certificate = Get-SSLCertificate -Thumbprint $thumbprint
  234.  
  235.             # If a certificate is found, log details and append it to the certificate info array
  236.             if ($certificate) {
  237.                 Write-Host "Certificate found: Issuer = $($certificate.Issuer), Thumbprint = $($certificate.Thumbprint)" -ForegroundColor Magenta
  238.        
  239.                 # Add certificate details to the array as a PowerShell object
  240.                 $certificateInfo += [PSCustomObject]@{
  241.                     "Issuer"          = $certificate.Issuer
  242.                     "Thumbprint"      = $certificate.Thumbprint
  243.                     "Expiration Date" = $certificate.NotAfter.ToString("yyyy-MM-dd'T'HH:mm:sszzz")
  244.                 }
  245.             } else {
  246.                 Write-Host "No certificate found for thumbprint: $thumbprint" -ForegroundColor Magenta
  247.             }
  248.         }
  249.     } else {
  250.         Write-Host "`nNo thumbprints found for site. Skipping certificate retrieval." -ForegroundColor Magenta
  251.     }
  252.  
  253.     return $certificateInfo
  254. }
  255.  
  256. # Function to format certificates into proper JSON-like structure
  257. function Format-SiteCertificates {
  258.     param (
  259.         [array]$certificateInfo  # Array of certificates to format
  260.     )
  261.  
  262.     Write-Host "`nFormatting site certificates..." -ForegroundColor Cyan
  263.  
  264.     # Check how many certificates are present and return the appropriate format
  265.     if ($certificateInfo.Count -gt 1) {
  266.         Write-Host "Multiple certificates found, formatting as array of objects." -ForegroundColor Cyan
  267.         return $certificateInfo  # Return as array of certificates
  268.     } elseif ($certificateInfo.Count -eq 1) {
  269.         Write-Host "Single certificate found, formatting as single object." -ForegroundColor Cyan
  270.         return $certificateInfo[0]  # Return single certificate object
  271.     } else {
  272.         Write-Host "No certificates found, returning null." -ForegroundColor Cyan
  273.         return $null  # No certificates, return null
  274.     }
  275. }
  276.  
  277. # Main logic to discover IIS sites, their bindings, and certificate details
  278. function Discover-IISSitesAndCertificates {
  279.     Ensure-WebAdministrationModule
  280.  
  281.     Write-Host "`nDiscovering IIS Sites and Certificates..." -ForegroundColor Green
  282.     $sites = Get-Website
  283.  
  284.     Write-Host "Found $($sites.Count) sites in IIS." -ForegroundColor Green
  285.     $discoveredSites = @()
  286.  
  287.     foreach ($site in $sites) {
  288.         Write-Host "`nProcessing site: $($site.Name)" -ForegroundColor White
  289.  
  290.         # Fetch and process the site's bindings
  291.         $bindings = Get-SiteBindings -SiteName $site.Name
  292.  
  293.         # Process the site bindings
  294.         $processedBindings = if ($bindings) {
  295.             Process-SiteBindings -bindings $bindings
  296.         } else {
  297.             Write-Host "No bindings found for site: $($site.Name)" -ForegroundColor White
  298.             $null
  299.         }
  300.  
  301.         if (-not $processedBindings) {
  302.             Write-Host "No valid bindings after processing for site: $($site.Name). Skipping..." -ForegroundColor White
  303.             continue
  304.         }
  305.  
  306.         # Call the Discover-SiteCertificates function to get the certificates
  307.         $certificateInfo = Discover-SiteCertificates -SiteName $site.Name
  308.  
  309.         # Format the certificates using the Format-SiteCertificates function
  310.         $formattedCertificateInfo = Format-SiteCertificates -certificateInfo $certificateInfo
  311.  
  312.         # Add the site details to the discoveredSites collection
  313.         Write-Host "Adding site to discovered sites list: $($site.Name)" -ForegroundColor White
  314.         $siteObject = [PSCustomObject]@{
  315.             Name         = $site.Name
  316.             ID           = $site.ID
  317.             State        = $site.State
  318.             PhysicalPath = $site.PhysicalPath
  319.             Bindings     = $processedBindings
  320.             Certificate  = $formattedCertificateInfo  # No ConvertTo-Json here
  321.         }
  322.  
  323.         $discoveredSites += $siteObject
  324.     }
  325.  
  326.     Write-Host "`nCompleted site and certificate discovery." -ForegroundColor Green
  327.  
  328.     # Convert the entire array to JSON at once
  329.     $discoveredSites | ConvertTo-Json -Depth 3 -Compress 3>$null
  330. }
  331.  
  332. # Execute the site and certificate discovery function
  333. Discover-IISSitesAndCertificates
  334.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement