Public/Get-ModernDomainScanReport.ps1
|
# Get-ModernDomainScanReport # https://dss.globalcyberalliance.org/api/v1/docs#tag/version # curl https://dss.globalcyberalliance.org/api/v1/scan/example.com function Get-ModernDomainScanReport { <# .SYNOPSIS Retrieves and optionally displays a domain security scan report from Global Cyber Alliance. .DESCRIPTION [Global Cyber Alliance](https://github.com/GlobalCyberAlliance/domain-security-scanner) .PARAMETER Domain The domain name to scan (e.g., example.com). .PARAMETER Raw If specified, returns the raw 'advice' object instead of formatted output. .EXAMPLE Get-ModernDomainScanReport -Domain "contoso.com" .EXAMPLE Get-ModernDomainScanReport -Domain "contoso.com" -Raw .LINK https://exchangepermissions.alweys.ch/modernmailtools/Get-ModernDomainScanReport .INPUTS None .OUTPUTS .NOTES #> [CmdletBinding(DefaultParameterSetName = 'Formatted')] param ( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$Domain, # $Domain = "globalcyberalliance.org" [Parameter(ParameterSetName = 'Advice')] [switch]$Advice, [Parameter(ParameterSetName = 'Advice')] [switch]$Raw, # Legacy alias for -Advice [Parameter(ParameterSetName = 'Result')] [switch]$Result, [Parameter(ParameterSetName = 'Advice')] [Parameter(ParameterSetName = 'Result')] [ValidateSet('domain', 'bimi', 'dkim', 'dmarc', 'mx', 'ns', 'spf')] [string]$Type ) $url = "https://dss.globalcyberalliance.org/api/v1/scan/$Domain" try { Write-Verbose "Requesting scan report from: $url" $response = Invoke-RestMethod -Uri $url -Method Get -ErrorAction Stop $hasTypeFilter = $PSBoundParameters.ContainsKey('Type') -and -not [string]::IsNullOrWhiteSpace($Type) if ($PSCmdlet.ParameterSetName -eq 'Advice') { if ($hasTypeFilter) { $prop = $response.advice.PSObject.Properties[$Type] if ($null -ne $prop) { return $prop.Value } return $null } return $response.advice } if ($PSCmdlet.ParameterSetName -eq 'Result') { # [bool]$response.scanResult.mx if ($hasTypeFilter) { $prop = $response.scanResult.PSObject.Properties[$Type] if ($null -ne $prop) { return $prop.Value } return $null } return $response.scanResult } if ($PSCmdlet.ParameterSetName -eq 'Formatted') { Write-Output "`n=== Advice Section ===`n" foreach ($key in $response.advice.PSObject.Properties.Name) { $value = $response.advice.$key if ($value -is [System.Collections.IEnumerable] -and -not ($value -is [string])) { Write-Output "${key}:`n$($value -join "`n")`n" } else { Write-Output "${key}: $value`n" } } $adviceHashtable = @{} foreach ($property in $response.advice.PSObject.Properties) { $adviceHashtable[$property.Name] = $property.Value } $evaluation = EvaluateAdvice -Advice $adviceHashtable Write-Output "`n=== Evaluation Section ===`n" Write-Output "Actionable Items:`n$($evaluation.ActionableItems -join "`n")`n" Write-Output "Warnings:`n$($evaluation.Warnings -join "`n")`n" Write-Output "Confirmations:`n$($evaluation.Confirmations -join "`n")`n" Write-Output "`n=== Scan Result Section ===`n" foreach ($key in $response.scanResult.PSObject.Properties.Name) { $value = $response.scanResult.$key if ($value -is [System.Collections.IEnumerable] -and -not ($value -is [string])) { Write-Output "${key}:`n$($value -join "`n")`n" } else { Write-Output "${key}: $value`n" } } } } catch { $err = $_ $contextMsg = "Failed to retrieve scan report for domain '$Domain' from '$url'." try { $err.ErrorDetails = [System.Management.Automation.ErrorDetails]::new($contextMsg) } catch { Write-Verbose "Could not set ErrorDetails: $($_.Exception.Message)" } $PSCmdlet.ThrowTerminatingError($err) } } function EvaluateAdvice { param ( [Parameter(Mandatory = $true)] [hashtable]$Advice ) $evaluation = @{ ActionableItems = @() Warnings = @() Confirmations = @() } foreach ($key in $Advice.Keys) { $value = $Advice[$key] if ($value -is [System.Collections.IEnumerable] -and -not ($value -is [string])) { foreach ($item in $value) { if ($item -match "fix|setup|recommended") { $evaluation.ActionableItems += "${key}: $item" } elseif ($item -match "couldn't|failed|not detected") { $evaluation.Warnings += "${key}: $item" } elseif ($item -match "is setup|no further action needed") { $evaluation.Confirmations += "${key}: $item" } else { $evaluation.Warnings += "${key}: $item" # Default to warnings for ambiguous cases } } } else { if ($value -match "fix|setup|recommended") { $evaluation.ActionableItems += "${key}: $value" } elseif ($value -match "couldn't|failed|not detected") { $evaluation.Warnings += "${key}: $value" } elseif ($value -match "is setup|no further action needed") { $evaluation.Confirmations += "${key}: $value" } else { $evaluation.Warnings += "${key}: $value" # Default to warnings for ambiguous cases } } } return $evaluation } |