From a95aaeb96d313490463a03d2bd93e3834a9cef34 Mon Sep 17 00:00:00 2001 From: Cameron Moore Date: Thu, 20 Feb 2025 15:17:03 -0600 Subject: [PATCH] Add DNS server IP address parameter to Invoke-Maester To allow the user to pass a custom DNS server IP address down to the underlying CISA Exchange tests, add a cmdlet parameter named DnsServerIpAddress to Invoke-Maester. The default value remains `1.1.1.1`. To enable passing custom data down to the tests, I began using the $PesterConfiguration.Run.Container property. The container will now hold the Path to the tests as well as the custom Data object. The DnsServerIpAddress parameter will be passed to all tests, but the parameter will be silently ignored by any tests without that parameter defined. --- powershell/public/Invoke-Maester.ps1 | 18 +++++++++++++----- .../public/cisa/exchange/Test-MtCisaDkim.ps1 | 5 ++++- .../exchange/Test-MtCisaDmarcAggregateCisa.ps1 | 5 ++++- .../exchange/Test-MtCisaDmarcRecordExist.ps1 | 5 ++++- .../exchange/Test-MtCisaDmarcRecordReject.ps1 | 5 ++++- .../cisa/exchange/Test-MtCisaDmarcReport.ps1 | 5 ++++- .../cisa/exchange/Test-MtCisaSpfDirective.ps1 | 7 +++++-- .../exchange/Test-MtCisaSpfRestriction.ps1 | 7 +++++-- tests/cisa/exchange/Test-MtCisaDkim.Tests.ps1 | 6 +++++- .../Test-MtCisaDmarcAggregateCisa.Tests.ps1 | 6 +++++- .../Test-MtCisaDmarcRecordExist.Tests.ps1 | 6 +++++- .../Test-MtCisaDmarcRecordReject.Tests.ps1 | 6 +++++- tests/cisa/exchange/Test-MtCisaDmarcReport.ps1 | 6 +++++- .../exchange/Test-MtCisaSpfDirective.Tests.ps1 | 6 +++++- .../Test-MtCisaSpfRestriction.Tests.ps1 | 6 +++++- 15 files changed, 78 insertions(+), 21 deletions(-) diff --git a/powershell/public/Invoke-Maester.ps1 b/powershell/public/Invoke-Maester.ps1 index a4132e9b..5a22b993 100644 --- a/powershell/public/Invoke-Maester.ps1 +++ b/powershell/public/Invoke-Maester.ps1 @@ -76,6 +76,11 @@ Invoke-Maester -PesterConfiguration $configuration ``` Runs all the Pester tests in the EIDSCA folder. +.EXAMPLE +Invoke-Maester -DnsServerIpAddress '8.8.8.8' + +Run all the tests while using a custom server IP address for DNS lookups. + .LINK https://maester.dev/docs/commands/Invoke-Maester #> @@ -164,7 +169,10 @@ function Invoke-Maester { ` # Skip the version check. # If set, the version check will not be performed. - [switch] $SkipVersionCheck + [switch] $SkipVersionCheck, + + # Optional. The DNS server IP address used for DNS lookups. + [string] $DnsServerIpAddress = '1.1.1.1' ) function GetDefaultFileName() { @@ -215,18 +223,18 @@ function Invoke-Maester { return $result } - function GetPesterConfiguration($Path, $Tag, $ExcludeTag, $PesterConfiguration) { + function GetPesterConfiguration($Path, $Tag, $ExcludeTag, $PesterConfiguration, $Data) { if (!$PesterConfiguration) { $PesterConfiguration = New-PesterConfiguration } $PesterConfiguration.Run.PassThru = $true $PesterConfiguration.Output.Verbosity = $Verbosity - if ($Path) { $PesterConfiguration.Run.Path = $Path } + if ($Path) { $PesterConfiguration.Run.Container = New-PesterContainer -Path $Path -Data $Data } else { if (Test-Path -Path "./powershell/tests/pester.ps1") { # Internal dev, exclude Maester's core tests - $PesterConfiguration.Run.Path = "./tests" + $PesterConfiguration.Run.Container = New-PesterContainer -Path './tests' -Data $Data } } if ($Tag) { $PesterConfiguration.Filter.Tag = $Tag } @@ -303,7 +311,7 @@ function Invoke-Maester { $Tag += "All" } - $pesterConfig = GetPesterConfiguration -Path $Path -Tag $Tag -ExcludeTag $ExcludeTag -PesterConfiguration $PesterConfiguration + $pesterConfig = GetPesterConfiguration -Path $Path -Tag $Tag -ExcludeTag $ExcludeTag -PesterConfiguration $PesterConfiguration -Data @{ DnsServerIpAddress = $DnsServerIpAddress } $Path = $pesterConfig.Run.Path.value Write-Verbose "Merged configuration: $($pesterConfig | ConvertTo-Json -Depth 5 -Compress)" diff --git a/powershell/public/cisa/exchange/Test-MtCisaDkim.ps1 b/powershell/public/cisa/exchange/Test-MtCisaDkim.ps1 index ebbe7623..49310873 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaDkim.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaDkim.ps1 @@ -17,6 +17,9 @@ function Test-MtCisaDkim { [CmdletBinding()] [OutputType([bool])] param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress, + # Selector-name for the DKIM record to test.. [string]$Selector = "selector1" ) @@ -51,7 +54,7 @@ function Test-MtCisaDkim { $selector = $config.SelectorBeforeRotateOnDate } - $dkimRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -DkimSelector $Selector -Records DKIM + $dkimRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -DkimSelector $Selector -Records DKIM -DnsServerIpAddress $DnsServerIpAddress $dkimRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $dkimRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/powershell/public/cisa/exchange/Test-MtCisaDmarcAggregateCisa.ps1 b/powershell/public/cisa/exchange/Test-MtCisaDmarcAggregateCisa.ps1 index 535e901b..8107fc7a 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaDmarcAggregateCisa.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaDmarcAggregateCisa.ps1 @@ -22,6 +22,9 @@ function Test-MtCisaDmarcAggregateCisa { [CmdletBinding()] [OutputType([bool])] param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress, + # Check all domains, not only .gov domains. [switch]$Force, @@ -69,7 +72,7 @@ function Test-MtCisaDmarcAggregateCisa { $dmarcRecords = @() foreach($domain in $expandedDomains){ - $dmarcRecord = Get-MailAuthenticationRecord -DomainName $domain -Records DMARC + $dmarcRecord = Get-MailAuthenticationRecord -DomainName $domain -Records DMARC -DnsServerIpAddress $DnsServerIpAddress $dmarcRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $dmarcRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordExist.ps1 b/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordExist.ps1 index 764cd1d2..15a33b69 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordExist.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordExist.ps1 @@ -17,6 +17,9 @@ function Test-MtCisaDmarcRecordExist { [CmdletBinding()] [OutputType([bool])] param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress, + # Check 2nd Level Domains Explicitly per CISA [switch]$Strict ) @@ -45,7 +48,7 @@ function Test-MtCisaDmarcRecordExist { $domainName = $domain.domainname } - $dmarcRecord = Get-MailAuthenticationRecord -DomainName $domainName -Records DMARC + $dmarcRecord = Get-MailAuthenticationRecord -DomainName $domainName -Records DMARC -DnsServerIpAddress $DnsServerIpAddress $dmarcRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $dmarcRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordReject.ps1 b/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordReject.ps1 index fb08bb40..0a930853 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordReject.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaDmarcRecordReject.ps1 @@ -17,6 +17,9 @@ function Test-MtCisaDmarcRecordReject { [CmdletBinding()] [OutputType([bool])] param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress, + # Check 2nd Level Domains Explicitly per CISA [switch]$Strict ) @@ -50,7 +53,7 @@ function Test-MtCisaDmarcRecordReject { $dmarcRecords = @() foreach($domain in $expandedDomains){ - $dmarcRecord = Get-MailAuthenticationRecord -DomainName $domain -Records DMARC + $dmarcRecord = Get-MailAuthenticationRecord -DomainName $domain -Records DMARC -DnsServerIpAddress $DnsServerIpAddress $dmarcRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $dmarcRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/powershell/public/cisa/exchange/Test-MtCisaDmarcReport.ps1 b/powershell/public/cisa/exchange/Test-MtCisaDmarcReport.ps1 index 6211de6f..10489753 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaDmarcReport.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaDmarcReport.ps1 @@ -20,6 +20,9 @@ function Test-MtCisaDmarcReport { [CmdletBinding()] [OutputType([bool])] param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress, + # Check 2nd Level Domains Explicitly per CISA [switch]$Strict ) @@ -53,7 +56,7 @@ function Test-MtCisaDmarcReport { $dmarcRecords = @() foreach($expandedDomain in $expandedDomains){ - $dmarcRecord = Get-MailAuthenticationRecord -DomainName $expandedDomain -Records DMARC + $dmarcRecord = Get-MailAuthenticationRecord -DomainName $expandedDomain -Records DMARC -DnsServerIpAddress $DnsServerIpAddress $dmarcRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $dmarcRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/powershell/public/cisa/exchange/Test-MtCisaSpfDirective.ps1 b/powershell/public/cisa/exchange/Test-MtCisaSpfDirective.ps1 index 39a53696..23115233 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaSpfDirective.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaSpfDirective.ps1 @@ -16,7 +16,10 @@ function Test-MtCisaSpfDirective { [CmdletBinding()] [OutputType([bool])] - param() + param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress + ) if(!(Test-MtConnection ExchangeOnline)){ Add-MtTestResultDetail -SkippedBecause NotConnectedExchange @@ -30,7 +33,7 @@ function Test-MtCisaSpfDirective { $spfRecords = @() foreach($domain in $sendingDomains){ - $spfRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -Records SPF + $spfRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -Records SPF -DnsServerIpAddress $DnsServerIpAddress $spfRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $spfRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/powershell/public/cisa/exchange/Test-MtCisaSpfRestriction.ps1 b/powershell/public/cisa/exchange/Test-MtCisaSpfRestriction.ps1 index 879798ac..b23d8e32 100644 --- a/powershell/public/cisa/exchange/Test-MtCisaSpfRestriction.ps1 +++ b/powershell/public/cisa/exchange/Test-MtCisaSpfRestriction.ps1 @@ -16,7 +16,10 @@ function Test-MtCisaSpfRestriction { [CmdletBinding()] [OutputType([bool])] - param() + param( + # DNS-server to use for lookup. + [string]$DnsServerIpAddress + ) if(!(Test-MtConnection ExchangeOnline)){ Add-MtTestResultDetail -SkippedBecause NotConnectedExchange @@ -32,7 +35,7 @@ function Test-MtCisaSpfRestriction { $spfRecords = @() foreach($domain in $acceptedDomains){ - $spfRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -Records SPF + $spfRecord = Get-MailAuthenticationRecord -DomainName $domain.DomainName -Records SPF -DnsServerIpAddress $DnsServerIpAddress $spfRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed" $spfRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value "" diff --git a/tests/cisa/exchange/Test-MtCisaDkim.Tests.ps1 b/tests/cisa/exchange/Test-MtCisaDkim.Tests.ps1 index f179df0f..b441e01f 100644 --- a/tests/cisa/exchange/Test-MtCisaDkim.Tests.ps1 +++ b/tests/cisa/exchange/Test-MtCisaDkim.Tests.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.3.1", "CISA", "Security", "All" { It "MS.EXO.03.1: DKIM SHOULD be enabled for all domains." { - $cisaDkim = Test-MtCisaDkim + $cisaDkim = Test-MtCisaDkim -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaDkim) { $cisaDkim | Should -Be $true -Because "DKIM record should exist and be configured." diff --git a/tests/cisa/exchange/Test-MtCisaDmarcAggregateCisa.Tests.ps1 b/tests/cisa/exchange/Test-MtCisaDmarcAggregateCisa.Tests.ps1 index 7de03eab..bc9c3e89 100644 --- a/tests/cisa/exchange/Test-MtCisaDmarcAggregateCisa.Tests.ps1 +++ b/tests/cisa/exchange/Test-MtCisaDmarcAggregateCisa.Tests.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.4.3", "CISA", "Security", "All" { It "MS.EXO.04.3: The DMARC point of contact for aggregate reports SHALL include reports@dmarc.cyber.dhs.gov." { - $cisaDmarcAggregateCisa = Test-MtCisaDmarcAggregateCisa + $cisaDmarcAggregateCisa = Test-MtCisaDmarcAggregateCisa -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaDmarcAggregateCisa) { $cisaDmarcAggregateCisa | Should -Be $true -Because "DMARC record includes proper aggregate target." diff --git a/tests/cisa/exchange/Test-MtCisaDmarcRecordExist.Tests.ps1 b/tests/cisa/exchange/Test-MtCisaDmarcRecordExist.Tests.ps1 index 3b4449c4..bff97d23 100644 --- a/tests/cisa/exchange/Test-MtCisaDmarcRecordExist.Tests.ps1 +++ b/tests/cisa/exchange/Test-MtCisaDmarcRecordExist.Tests.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.4.1", "CISA", "Security", "All" { It "MS.EXO.04.1: A DMARC policy SHALL be published for every second-level domain." { - $cisaDmarcRecordExist = Test-MtCisaDmarcRecordExist + $cisaDmarcRecordExist = Test-MtCisaDmarcRecordExist -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaDmarcRecordExist) { $cisaDmarcRecordExist | Should -Be $true -Because "DMARC record should exist." diff --git a/tests/cisa/exchange/Test-MtCisaDmarcRecordReject.Tests.ps1 b/tests/cisa/exchange/Test-MtCisaDmarcRecordReject.Tests.ps1 index fd39cb41..560a88ab 100644 --- a/tests/cisa/exchange/Test-MtCisaDmarcRecordReject.Tests.ps1 +++ b/tests/cisa/exchange/Test-MtCisaDmarcRecordReject.Tests.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.4.2", "CISA", "Security", "All" { It "MS.EXO.04.2: The DMARC message rejection option SHALL be p=reject." { - $cisaDmarcRecordReject = Test-MtCisaDmarcRecordReject + $cisaDmarcRecordReject = Test-MtCisaDmarcRecordReject -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaDmarcRecordReject) { $cisaDmarcRecordReject | Should -Be $true -Because "DMARC record policy should be reject." diff --git a/tests/cisa/exchange/Test-MtCisaDmarcReport.ps1 b/tests/cisa/exchange/Test-MtCisaDmarcReport.ps1 index e36c74ca..3c7547f2 100644 --- a/tests/cisa/exchange/Test-MtCisaDmarcReport.ps1 +++ b/tests/cisa/exchange/Test-MtCisaDmarcReport.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.4.4", "CISA", "Security", "All" { It "MS.EXO.04.4: An agency point of contact SHOULD be included for aggregate and failure reports." { - $cisaDmarcReport = Test-MtCisaDmarcReport + $cisaDmarcReport = Test-MtCisaDmarcReport -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaDmarcReport) { $cisaDmarcReport | Should -Be $true -Because "DMARC report targets should exist." diff --git a/tests/cisa/exchange/Test-MtCisaSpfDirective.Tests.ps1 b/tests/cisa/exchange/Test-MtCisaSpfDirective.Tests.ps1 index 93c2b57d..93422d41 100644 --- a/tests/cisa/exchange/Test-MtCisaSpfDirective.Tests.ps1 +++ b/tests/cisa/exchange/Test-MtCisaSpfDirective.Tests.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.2.2", "CISA", "Security", "All" { It "MS.EXO.02.2: An SPF policy SHALL be published for each domain, designating only these addresses as approved senders." { - $cisaSpfDirective = Test-MtCisaSpfDirective + $cisaSpfDirective = Test-MtCisaSpfDirective -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaSpfDirective) { $cisaSpfDirective | Should -Be $true -Because "SPF record should restrict authorized senders." diff --git a/tests/cisa/exchange/Test-MtCisaSpfRestriction.Tests.ps1 b/tests/cisa/exchange/Test-MtCisaSpfRestriction.Tests.ps1 index 0cfda9c1..d27a0d3f 100644 --- a/tests/cisa/exchange/Test-MtCisaSpfRestriction.Tests.ps1 +++ b/tests/cisa/exchange/Test-MtCisaSpfRestriction.Tests.ps1 @@ -1,6 +1,10 @@ +param( + [string]$DnsServerIpAddress +) + Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.2.1", "CISA", "Security", "All" { It "MS.EXO.02.1: A list of approved IP addresses for sending mail SHALL be maintained." { - $cisaSpfRestriction = Test-MtCisaSpfRestriction + $cisaSpfRestriction = Test-MtCisaSpfRestriction -DnsServerIpAddress $DnsServerIpAddress if ($null -ne $cisaSpfRestriction) { $cisaSpfRestriction | Should -Be $true -Because "SPF record should restrict authorized senders."