AzStackHCIDNS/AzStackHci.DNS.Helpers.psm1
|
Import-LocalizedData -BindingVariable ldTxt -FileName AzStackHci.DNS.Strings.psd1 # This file contains a list of discreet tests that can be run against the environment # Each test named Test-* is exported and discovered to be run by the user-facing function. # The user uses Include and Exclude parameters to run specific tests. (this provides a consistent experience across validators) # If tests have dependencies on other tests, or they should be run in a specific order, the pattern describe above should be removed. function Test-ExternalDnsResolution { <# .SYNOPSIS Validates external hostname resolution from all cluster nodes. .DESCRIPTION Tests that each configured DNS server on every cluster node can resolve an external hostname (default: microsoft.com). Uses Resolve-DnsName -DnsOnly against each DNS server independently. Retries up to 3 times with 5-second delays. Enables the DNS Client operational event log on the final retry attempt for diagnostic capture. If a web proxy is enabled (via netsh winhttp show advproxy), the test is skipped because the proxy may handle DNS resolution. Asserts: All DNS servers on all nodes can resolve the external hostname. Severity: CRITICAL — failure indicates broken outbound DNS which blocks deployment. .PARAMETER PsSession PowerShell remoting sessions to each cluster node. .PARAMETER ExternalName The external hostname to resolve. Defaults to 'microsoft.com' if not specified. Exactly one name must be provided. #> [CmdletBinding()] param ( [System.Management.Automation.Runspaces.PSSession[]] $PsSession, [string[]] $ExternalName ) $SkipDnsWithProxy = $ldTxt.SkipDnsWithProxy # Test if proxy is enabled and return because proxy maybe doing dns resolution function IsProxyEnabled { $line1, $line2, $line3, $JsonLines = netsh winhttp show advproxy $proxy = $JsonLines | ConvertFrom-Json -ErrorAction SilentlyContinue [bool]$proxy.Proxy } if (IsProxyEnabled) { $testDnsServer = @{ Resource = $SkipDnsWithProxy Status = 'SUCCESS' TimeStamp = [datetime]::UtcNow Source = $ENV:COMPUTERNAME Detail = $SkipDnsWithProxy -f $ENV:COMPUTERNAME } } else { if ([string]::IsNullOrEmpty($PSBoundParameters['ExternalName'])) { Log-Info "No DNS target found, using microsoft.com as fall back" -ConsoleOut -Type Warning $ExternalName = @('microsoft.com') } if ($ExternalName.count -ne 1) { throw "Expected 1 System_Check_DNS_External_Hostname_Resolution, found $($ExternalName.count)" } $TestDNSResolutionParams = @{} if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } if ($PSBoundParameters['ExternalName']) { $TestDNSResolutionParams.Add('TargetName', $ExternalName) } $testDnsServer = TestDNSResolution @TestDNSResolutionParams } # Write result to verbose log $testDnsServer | Foreach-Object { Log-Info $_.Detail -Type $(if ( $_.Status -eq 'FAILURE' ){ "Critical" } else { "INFO" } ) } # Collect lightweight per-node results for aggregation $detailResults = @() $detailResults += $testDnsServer | Foreach-Object { New-LightweightResult ` -Name 'AzStackHci_DNS_Test_External_Hostname_Resolution' ` -Status $PsItem.Status ` -Severity 'Critical' ` -TargetResourceName "$($PsItem.Source)/$($PsItem.Resource)" ` -Source $PsItem.Source ` -Resource $PsItem.Resource ` -Detail $PsItem.Detail } return @(New-AggregatedTestResult ` -TestName 'Test-ExternalDnsResolution' ` -DisplayName 'External DNS Resolution' ` -Description 'Validates external hostname resolution from each cluster node. Uses Resolve-DnsName -DnsOnly against all configured DNS servers to verify that the target hostname (default: microsoft.com) can be resolved. Tests each DNS server independently with up to 3 retries and 5-second delays between attempts. Enables DNS Client operational log on final retry for diagnostics.' ` -DetailResults $detailResults ` -ValidatorName 'DNS' ` -ResourceType 'DNS' ` -Remediation $ldTxt.ExternalDnsRemediation) } function Test-ActiveDirectoryDomainName { <# .SYNOPSIS Validates Active Directory domain FQDN resolution from all cluster nodes. .DESCRIPTION Tests that each configured DNS server on every cluster node can resolve the Active Directory domain FQDN. Uses Resolve-DnsName -DnsOnly against each DNS server independently with up to 3 retries and 5-second delays between attempts. Enables the DNS Client operational event log on the final retry for diagnostics. A resolvable AD domain name is required for domain join and cluster lifecycle operations. Asserts: All DNS servers on all nodes return a valid response for the domain FQDN. Severity: CRITICAL — failure blocks domain join. .PARAMETER PsSession PowerShell remoting sessions to each cluster node. .PARAMETER DomainFQDN The Active Directory domain FQDN to resolve (e.g., 'contoso.local'). #> [CmdletBinding()] param ( [System.Management.Automation.Runspaces.PSSession[]] $PsSession, [string[]] $DomainFQDN ) $TestDNSResolutionParams = @{} if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } if ($PSBoundParameters['DomainFQDN']) { $TestDNSResolutionParams.Add('TargetName', $DomainFQDN) } $testDnsServer = TestDNSResolution @TestDNSResolutionParams # Write result to verbose log $testDnsServer | Foreach-Object { Log-Info $_.Detail -Type $(if ( $_.Status -eq 'FAILURE' ){ "Critical" } else { "INFO" } ) } # Collect lightweight per-node results for aggregation $detailResults = @() $detailResults += $testDnsServer | Foreach-Object { New-LightweightResult ` -Name 'AzStackHci_DNS_Test_ActiveDirectory_DomainName_Resolution' ` -Status $PsItem.Status ` -Severity 'Critical' ` -TargetResourceName "$($PsItem.Source)/$($PsItem.Resource)" ` -Source $PsItem.Source ` -Resource $PsItem.Resource ` -Detail $PsItem.Detail } return @(New-AggregatedTestResult ` -TestName 'Test-ActiveDirectoryDomainName' ` -DisplayName 'Active Directory Domain Name Resolution' ` -Description 'Validates that the Active Directory domain FQDN can be resolved from each cluster node. Queries all configured DNS servers using Resolve-DnsName -DnsOnly with up to 3 retries per server. A resolvable AD domain name is required for domain join and cluster operations.' ` -DetailResults $detailResults ` -ValidatorName 'DNS' ` -ResourceType 'DNS' ` -Remediation $ldTxt.DomainNameDnsRemediation) } function Test-IPMapForClusterNodes { <# .SYNOPSIS Validates that DNS A records for cluster nodes resolve to their expected IP addresses. .DESCRIPTION For each node in the physicalNodesSettings, constructs the FQDN (nodeName.domainFQDN) and queries all configured DNS servers using Resolve-DnsName -DnsOnly with up to 3 retries and 5-second delays. Compares the returned IP addresses against the expected management IP from the deployment answer file. Asserts: Each node FQDN resolves to its expected IP address on every DNS server. Severity: INFORMATIONAL — mismatches are reported but do not block deployment because DNS records may be created dynamically during domain join. .PARAMETER PhysicalMachineIpMap Hashtable mapping node hostnames to their expected management IP addresses. .PARAMETER DomainFQDN The Active Directory domain FQDN used to construct node FQDNs. .PARAMETER PsSession PowerShell remoting sessions to each cluster node. #> [CmdletBinding()] param ( [hashtable] $PhysicalMachineIpMap, [string] $DomainFQDN, [System.Management.Automation.Runspaces.PSSession[]] $PsSession ) try { $TestDNSResolutionParams = @{} if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } $IpMap = @{} foreach ($key in $PhysicalMachineIpMap.Keys) { $fqdnKey = "$key.$DomainFQDN" $IpMap.Add($fqdnKey, $PhysicalMachineIpMap[$key]) } $TestDNSResolutionParams.Add('IpMap', $IpMap) $result = TestDNSResolution @TestDNSResolutionParams $detailResults = @() foreach ($res in $result) { Log-Info $res.Detail -Type $(if ( $res.Status -eq 'FAILURE' ){ "Critical" } else { "INFO" } ) $detailResults += New-LightweightResult ` -Name 'AzStackHci_DNS_Test_IPMap_For_Cluster_Nodes' ` -Status $res.Status ` -Severity 'INFORMATIONAL' ` -TargetResourceName "$($res.Source)/$($res.Resource)" ` -Source $res.Source ` -Resource $res.Resource ` -Detail $res.Detail } return @(New-AggregatedTestResult ` -TestName 'Test-IPMapForClusterNodes' ` -DisplayName 'IP Map For Cluster Nodes' ` -Description 'Validates that DNS A records for each node in physicalNodesSettings resolve to the expected IP addresses. For each node, constructs the FQDN (nodeName.domainFQDN) and queries all configured DNS servers using Resolve-DnsName -DnsOnly. Compares returned IP addresses against the expected IP from the deployment answer file. Retries up to 3 times with 5-second delays.' ` -DetailResults $detailResults ` -ValidatorName 'DNS' ` -ResourceType 'DNS' ` -Remediation $ldTxt.IPMapRemediation) } catch { Log-Info "Test-IPMapForClusterNodes failed with error: $_" -Type WARNING } } function Test-LocalClusterDNSResolution { <# .SYNOPSIS Validates that all cluster node names and the cluster name are resolvable in DNS. .DESCRIPTION Constructs FQDNs for each node (nodeName.domainFqdn) and the cluster (clusterName.domainFqdn), then queries all configured DNS servers using Resolve-DnsName -DnsOnly with up to 3 retries and 5-second delays. All names must be resolvable for cluster formation and lifecycle operations. If resolution fails and the environment uses Active Directory (not LocalIdentity), a secondary test checks for AD-integrated DNS zones via LDAP (TestAdIntegratedDns). If AD-integrated DNS is present, the local resolution failure is downgraded to INFORMATIONAL because cluster names will be dynamically registered during domain join. Asserts: Every DNS server can resolve all node FQDNs and the cluster FQDN. Severity: CRITICAL (downgraded to INFORMATIONAL if AD-integrated DNS passes). .PARAMETER PsSession PowerShell remoting sessions to each cluster node. .PARAMETER PhysicalMachineNames Array of node hostnames (short names without domain suffix). .PARAMETER ClusterName The cluster name (short name without domain suffix). .PARAMETER DomainFqdn The Active Directory domain FQDN for constructing fully-qualified names. .PARAMETER DomainCredential Credential for AD-integrated DNS zone lookup (used in fallback test). .PARAMETER IsLocalIdentityEnvironment Switch indicating an AD-less (LocalIdentity) deployment. When set, the AD-integrated DNS fallback test is skipped and failures remain CRITICAL. #> [CmdletBinding()] param ( [System.Management.Automation.Runspaces.PSSession[]] $PsSession, [string[]] $PhysicalMachineNames, [string] $ClusterName, # AD integration parameters [Parameter()] [System.String] $DomainFqdn, [Parameter()] [System.Management.Automation.PSCredential] $DomainCredential, [Parameter()] [switch] $IsLocalIdentityEnvironment ) $TestDNSResolutionParams = @{} $severity = 'Critical' if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } # Add fully qualified cluster and node names to resolve. # Cluster name is already fully qualified, so just add it to the list. $targetNames = @() $targetNames += $PhysicalMachineNames | ForEach-Object { "$_.$DomainFqdn" } $targetNames += "$ClusterName.$DomainFqdn" $TestDNSResolutionParams.Add('TargetName', $targetNames) $testDnsServer = TestDNSResolution @TestDNSResolutionParams # Write result to verbose log $testDnsServer | Foreach-Object { Log-Info $_.Detail -Type $(if ( $_.Status -eq 'FAILURE' ){ $severity } else { "INFO" } ) } # Collect lightweight per-node results for aggregation $detailResults = @() $detailResults += $testDnsServer | Foreach-Object { New-LightweightResult ` -Name 'AzStackHci_DNS_Test_Local_Cluster_DNS_Resolution' ` -Status $PsItem.Status ` -Severity $severity ` -TargetResourceName "$($PsItem.Source)/$($PsItem.Resource)" ` -Source $PsItem.Source ` -Resource $PsItem.Resource ` -Detail $PsItem.Detail } $LocalClusterDNSResult = @(New-AggregatedTestResult ` -TestName 'Test-LocalClusterDNSResolution' ` -DisplayName 'Local Cluster DNS Resolution' ` -Description 'Validates that each DNS server can resolve all cluster node names and the cluster name. Constructs FQDNs for each node (nodeName.domainFqdn) and the cluster (clusterName.domainFqdn), then queries all configured DNS servers using Resolve-DnsName -DnsOnly with up to 3 retries and 5-second delays. All names must be resolvable for cluster formation and lifecycle operations.' ` -DetailResults $detailResults ` -ValidatorName 'DNS' ` -ResourceType 'DNS' ` -Remediation $ldTxt.LocalClusterDnsRemediation) # Check if the test failed and if so, check if AD integration test parameters are set # If AD integration test parameters are set, run the AD integrated DNS test # If the AD integrated DNS test fails, return the result of the AD integrated DNS test (critical) and the local cluster DNS test (critical) # If the AD integrated DNS test passes, return the result of the non AD integrated DNS test if ('FAILURE' -in $LocalClusterDNSResult.Status) { Log-Info -Message "Local Cluster member DNS resolution test failed. Checking if AD integration test parameters are set." -Type $severity # AD deployment's have DomainCredential and DomainFqdn set, AD-less deployments do not have these parameters set. if (-not $PSBoundParameters['IsLocalIdentityEnvironment']) { Log-Info -Message "AD integration test parameters are set. Running AD integrated DNS test." -Type $severity $adIntDnsResult = TestAdIntegratedDns -DomainFqdn $DomainFqdn -DomainCredential $DomainCredential # both tests have failed return both results if ($adIntDnsResult.Status -eq 'FAILURE') { Log-Info -Message "AD integrated DNS test failed. Returning both local resolution and AD integrated together" -Type $severity return ($LocalClusterDNSResult + $adIntDnsResult) } else { # This is happy path AD deployment has AD integrated DNS. Log-Info -Message "AD integrated DNS test passed. We don't need to block the life cycle operation. Returning AD Integrated DNS test result and downgrading A record test to informational." $LocalClusterDNSResult | ForEach-Object { $_.Severity = 'INFORMATIONAL' if ($_.AdditionalData -and $_.AdditionalData.ContainsKey('Detail')) { $_.AdditionalData['Detail'] += "`n[Severity downgraded from CRITICAL to INFORMATIONAL: AD Integrated DNS passed, cluster names will be dynamically registered]" } } return ($LocalClusterDNSResult + $adIntDnsResult) } } else { Log-Info -Message "AD integration test parameters are not set. Local Cluster member DNS resolution test failed. This will block lifecycle operation." -Type $severity return $LocalClusterDNSResult } } else { Log-info -Message "Local Cluster member DNS resolution test passed. Returning." return $LocalClusterDNSResult } } function TestDNSResolution { <# .SYNOPSIS Test DNS Resolution of a target name by testing each dns server configured on any remote machine. .DESCRIPTION This function will test the DNS resolution of a target name by testing each DNS server configured on the machine. It will return the status of each DNS server and the result of the DNS query. It will also enable the DNS client operational log to get the logs for last attempt during failures. It will then disable the log if it was not enabled in the first place. It's intended to be a reusable function to facilitate the testing of DNS resolution in a consistent manner across types of names internal/external/node/cluster etc. #> [CmdletBinding()] param ( [string[]] $TargetName, [hashtable] $IpMap, [System.Management.Automation.Runspaces.PSSession[]] $PsSession ) try { # scriptblock to test dns resolution for each dns server $testDnsSb = { $TargetName = $args[0] -split ' ' $IpMap = $args[1] # Pass in localized strings $NoDnsConfigured = $args[2] $QueryDnsFail = $args[3] $QueryDnsPass = $args[4] $ExpectedDnsResultPass = $args[5] $ExpectedDnsResultFail = $args[6] $AdditionalData = @() # Get local DNS servers $dnsServers = @() $netAdapter = Get-NetAdapter | Where-Object Status -EQ Up $dnsServer = Get-DnsClientServerAddress -InterfaceIndex $netAdapter.ifIndex -AddressFamily IPv4 $dnsServers += $dnsServer | ForEach-Object { $PSITEM.Address } | Sort-Object | Get-Unique # set target name to ipmap key if applicable $UseMap = ![string]::IsNullOrEmpty($IpMap) if ($UseMap) { $TargetName = $IpMap.Keys } if (-not $dnsServers) { return @{ Resource = $NoDnsConfigured Status = 'FAILURE' TimeStamp = [datetime]::UtcNow Source = $ENV:COMPUTERNAME Detail = $NoDnsConfigured } } else { foreach ($target in $TargetName) { foreach ($dnsServer in $dnsServers) { $status = 'FAILURE' $attempt = 0 $maxRetry = 3 $sleepInSeconds = 5 while ($attempt -lt $maxRetry -and $status -eq 'FAILURE') { try { $attempt++ $dnsFailure = $null # if this is the last attempt, check if the DNS client operational log is enabled, enabled it and reads the log for debug information if ($attempt -eq ($maxRetry - 1)) { $wevtutilglcmd = "& wevtutil gl Microsoft-Windows-DNS-Client/Operational" $dnsLogState = Invoke-Expression -command $wevtutilglcmd | select-string -pattern "enabled: (.*)" if ($dnsLogState -like '*false') { # enable the dns log for 5 minutes to get the logs and set the size to 10MB & wevtutil sl Microsoft-Windows-DNS-Client/Operational /e:true /ms:10485760 $dnsLogNeedsToBeDisabled = $true } else { $dnsLogAlreadyEnabled = $true } $preDnsTimeStamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffZ" -AsUTC } $dnsResult = Resolve-DnsName -Name $target -Server $dnsServer -DnsOnly -ErrorAction SilentlyContinue -QuickTimeout -Type A } catch { $dnsFailure = $_.Exception.Message } if ([int]($dnsResult.count) -eq 0) { $detail = $QueryDnsFail -f $dnsServer, $target, $ENV:COMPUTERNAME, "$attempt/$maxRetry", [int]($dnsResult.count), $dnsFailure } else { $detail = $QueryDnsPass -f $dnsServer, $target, $ENV:COMPUTERNAME, "$attempt/$maxRetry", [int]($dnsResult.count), ($dnsResult.IpAddress -join ',') } if ($dnsResult) { if ($dnsResult[0] -is [Microsoft.DnsClient.Commands.DnsRecord]) { # If there is no IpMap provided, consider any valid response as success if (!$UseMap) { $status = 'SUCCESS' break } else { # If there the IpMap is provided but we don't have an expected IP for this target, consider any valid response as success # When we do have an expected IP for this target, check if the returned IPs contain the expected IP if ( -not $IpMap.ContainsKey($target) ) { $status = 'SUCCESS' break } else { # Check if the returned IPs contain the expected IP if ($dnsResult.IpAddress -contains $IpMap[$target]) { $status = 'SUCCESS' $detail = "`r`n" + ($ExpectedDnsResultPass -f $target, $ENV:COMPUTERNAME, $IpMap[$target], ($dnsResult.IpAddress -join ','), $dnsServer, "$attempt/$maxRetry") break } else { $status = 'FAILURE' $detail = "`r`n" + ($ExpectedDnsResultFail -f $target, $ENV:COMPUTERNAME, $IpMap[$target], ($dnsResult.IpAddress -join ','), $dnsServer, "$attempt/$maxRetry") } } } } else { $status = 'FAILURE' } } else { $status = 'FAILURE' } Start-Sleep -Second $sleepInSeconds } # If the dns log is enabled get the dns logs for this domain if ($dnsLogNeedsToBeDisabled -eq $true -or $dnsLogAlreadyEnabled) { $xPathFilter = "*[System[Provider[@Name='Microsoft-Windows-DNS-Client']]] and *[EventData[Data[@Name='QueryName']='$target']] and *[System[TimeCreated[@SystemTime > '$preDnsTimeStamp']]]" $dnsEvents = Get-WinEvent -LogName "Microsoft-Windows-DNS-Client/Operational" -FilterXPath $xPathFilter -ErrorAction SilentlyContinue | sort-object TimeCreated | Foreach-Object { "[{0}] [{1}] - {2}" -f $_.TimeCreated, $_.LevelDisplayName, $_.Message} if ($dnsEvents) { $detail += "`n`nDNS Client Operational Log:`n$($dnsEvents -join "`r`n" | Out-String)" } # Disable the DNS client operational log if it was enabled in the first place if ($dnsLogNeedsToBeDisabled -eq $true) { $wevtutilslCmd = "& wevtutil sl Microsoft-Windows-DNS-Client/Operational /e:false" Invoke-Expression -Command $wevtutilslCmd } } $AdditionalData += @{ Resource = $dnsServer Status = $status TimeStamp = [datetime]::UtcNow Source = $ENV:COMPUTERNAME Detail = $detail } } } } $AdditionalData } # run scriptblock $dnsargs = @{ ArgumentList = $TargetName, $IpMap, $ldTxt.NoDnsConfigured, $ldTxt.QueryDnsFail, $ldTxt.QueryDnsPass, $ldTxt.ExpectedDnsResultPass, $ldTxt.ExpectedDnsResultFail } $testDnsServer = if ($PsSession) { Invoke-Command -Session $PsSession -ScriptBlock $testDnsSb @dnsArgs } else { Invoke-Command -ScriptBlock $testDnsSb @dnsArgs } return $testDnsServer } catch { throw "Failed to run TestDNSResolution: $($_.Exception.Message)" } } function Get-LdapDomain { [CmdletBinding()] [OutputType([System.String])] Param ( [Parameter(Mandatory = $true)] [System.String] $Domain ) $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop $ldapDomain = ($Domain.Split('.') | ForEach-Object {"DC=$_"}) -join ',' return $ldapDomain } function TestAdIntegratedDns { [CmdletBinding()] [OutputType([System.Boolean])] Param ( [Parameter(Mandatory = $true)] [System.String] $DomainFqdn, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $DomainCredential ) try { $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop $severity = 'Critical' Log-Info -Message 'Importing module ActiveDirectory.' Import-Module ActiveDirectory -Verbose:$false # Convert domain name to fully qualified LDAP name $ldapDomain = Get-LdapDomain -Domain $DomainFqdn Log-Info -Message "LdapDomain to search is '$ldapDomain'." # Get forest root domain so we can search for forest zones as well as domain zones $rootDomain = Get-LdapDomain -Domain (Get-ADForest -Credential $DomainCredential -Server $DomainFqdn).RootDomain Log-Info -Message "RootDomain to search is '$rootDomain'." # Build list of locations to search - including legacy Windows 2000 locations $searchBases = @( "DC=$DomainFqdn,CN=MicrosoftDNS,DC=DomainDnsZones,$ldapDomain" "DC=$DomainFqdn,CN=MicrosoftDNS,CN=System,$ldapDomain" "DC=$DomainFqdn,CN=MicrosoftDNS,DC=ForestDnsZones,$rootDomain" "DC=$DomainFqdn,CN=MicrosoftDNS,CN=System,$rootDomain" ) $result = $false # Search each location until one is found foreach ($searchBase in $searchBases) { if (-not $result) { Log-Info -Message "Searching for DNS zone container '$searchBase'." try { $dnsZone = Get-ADObject -SearchBase $searchBase -LDAPFilter '(objectClass=dnsZone)' -Properties @('dnsProperty') -Credential $DomainCredential -Server $DomainFqdn Log-Info -Message "Found DNS zone container '$searchBase'." $result = $true } catch { Log-Info -Message "DNS zone container '$searchBase' does not exist." } } } # Write to log file and set status if ($result) { $dtl = $ldTxt.AdIntDnsPass -f $rootDomain, $dnsZone.DistinguishedName Log-Info -Message $dtl $Status = 'SUCCESS' } else { $dtl = $ldTxt.AdIntDnsFail -f $rootDomain Log-Info -Message $dtl -Type $severity $Status = 'FAILURE' } # Write result $now = [datetime]::UtcNow $params = @{ Name = 'AzStackHci_DNS_Test_ActiveDirectory_Integrated_DNS' Title = 'Test Active Directory Integrated DNS' DisplayName = 'Test Active Directory Integrated DNS' Severity = $severity Description = 'Test Active Directory Integrated DNS' Tags = @{ Service = 'System' } Remediation = $ldTxt.AdIntDnsRemediation TargetResourceID = "$ENV:COMPUTERNAME/$rootDomain" TargetResourceName = $rootDomain TargetResourceType = 'DNS' Timestamp = $now Status = $Status AdditionalData = @{ Resource = $rootDomain Source = $ENV:COMPUTERNAME Status = $Status Detail = $dtl } HealthCheckSource = $ENV:EnvChkrId } return (New-AzStackHciResultObject @params) } catch { throw "Error checking Active Directory Integrated DNS: $_" } } Export-ModuleMember -Function Test-* # SIG # Begin signature block # MIInSQYJKoZIhvcNAQcCoIInOjCCJzYCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBOQpk4c1Uv2Rp4 # x+nNezTeHrkv0m6Q0QT2Oi9ZtTYXUqCCDLowggX1MIID3aADAgECAhMzAAACHU0Z # yE7XD1dIAAAAAAIdMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD # b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQzWhcNMjcwNDE1MTg1 # OTQzWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD # VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB # DwAwggEKAoIBAQDQvewXxx9gZZFC6Ys1WBay8BJ8kGA4JQnH5CMafqOASlTpK9H8 # o5ZXTXt0caVQTNMUPt445wXYD+dFtaKWTwDn1I52oUSrC9vJin1Gsqt+zyKJL5Dg # 3eQXbQNR61DmMy20GLTIO3SFed9Rfi/ophgCLGFLDR3r0KvHjwMb/jYWS0celV/4 # Lz27LfAekm8v9E5IXaeiXbAUYZKK090n4CVl3JBtbN+9DtI9SNu/yjvozW52/u7R # X/Ttpa/KDlpuokZ+Zcbvmtd9ur9gFLvZzh41o9MsE/clQtdaFWGvuo6Jua/ntpgk # ey3E5/vBFe+MJPG6phdnuo6r57ZudCudiI1bAgMBAAGjggGbMIIBlzAOBgNVHQ8B # Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O # BBYEFH6QuMwqcPG0hQlQ6c5jCtTTLrVeMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQL # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzMDAxMis1MDc1NTkw # HwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEwYAYDVR0fBFkwVzBVoFOg # UYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0 # JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNybDBtBggrBgEFBQcBAQRh # MF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy # dDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQBKTbYOjzwTG/DXGaz9 # s6+fQeaTtDcFmMY+5UyVFCyj7Pv+5i37qfX8lSL/tBIfYQfWsMuBQlfZurJD6r4H # VJ2CeH+1fgiq8dcHdVKoZ3Sa2qXoX3cq9iS8cVb06B7+5/XJ7I0OxHH9fDsvJ3T3 # w5V/ZtAIFmLrl+P0CtG+92uzRsn0nTbdFjOkLMLWPLAU3THohKRlSEMgFJpPkm5n # 5UAZ35xX6FWCrDLsSKb555bTifwa8mJBwdlof0bmfYidH+dxZ1FdDxvLnNl9zeKs # A4kejaaIqqIPguhwAti5Ql7BlTNoJNwxCvBmqW2MQLnCkYN/VVUsR3V2x/rcTNzo # Bf/Z/SpROvdaA2ZOOd1uioXJt3tdLQ7vHpqpib0KfWr/FWXW10q38VxfCnRQBqzb # SuztR7nEMuzX7Ck+B/XaPDXd1qh72+QYyB0Z2VzWmO9zsnb9Uq/dwu8LGeQqnyu6 # 7SDGACvnXii2fb9+US492VTnXSnFKyqwgzUyFMtZK1/sHYTv6bG4TtQUygQxTN+Z # V+aJIlKO2MqZ7bKrAnOzS9m6NgoTdWOq11bTOZwKlIEV/EhV9SWkDmdpR/hPPT2v # 6TEj4F8PT/zHjRezIU5c/DGlt/VhY/pK0XkJtEyMmmS1BMtjU/rqBZVMIm3dnxQs # /TBByr+Cf8Z1r7aifQVQ+WSqzjCCBr0wggSloAMCAQICEzMAAAA5O7Y3Gb8GHWcA # AAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl # IEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoXDTM2MDMyMjIyMTMwNFow # VzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEo # MCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAyNDCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeqlRYHNa265v4IY9fH8TKh # emHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo0dtS/EW6I/yEL/bLSY8h # KpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATvQVL4tcf03aTycsz8QeCd # M0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a1uv1zerOYMnsneRRwCbp # yW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1FyQfK0fVkaya8SmVHQ/t # Of23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfOGSWHIIV4YrTJTT6PNty5 # REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7ttOu1bVnXfHaqPYl2rPs # 20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJuz2MXMCt7iw7lFPG9LXK # Gjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxSCwyoGIq0PhaA7Y+VPct5 # pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOmVQop36wUVUYklUy++vDW # eEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3SkE/xIkgpfl22MM1itkZ # 35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGC # NxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPXLQaUEggxMBkGCSsGAQQB # gjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU # ci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0MjAx # MV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUHMAKGQmh0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0MjAx # MV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAFJQfOChP7onn6fLI # MKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D5W4wMwYeLystcEqfkjz4 # NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBYnbu0+THSuVHTe0VTTPVh # ily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSIvgn0JksVBVMYVI5QFu/q # hnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6aR9y34aiM1qmxaxBi6OU # nyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4wPKC5OmHm1DQIt/MNokbb # H3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7RTX8AdBPo0I6OEojf39z # uFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK/fg8B2qjW88MT/WF5V5u # vZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSKYBv0VisCzfxgeU+dquXW # 9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkwYTu/9dLeH2pDqeJZAABV # DWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVTQl0v4q8J/AUmQN5W4n10 # 1cY2L4A7GTQG1h32HHAvfQESWP0xghnlMIIZ4QIBATBuMFcxCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jv # c29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIdTRnITtcPV0gAAAAAAh0w # DQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYK # KwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICM6fMDi # tSSlgOy9cAEBEiwqdR/pArY+S+5py5GxD/QtMEIGCisGAQQBgjcCAQwxNDAyoBSA # EgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w # DQYJKoZIhvcNAQEBBQAEggEAsTJKcojW4d1j6KpSVXVLgOfikl964bI1KdsYUvQd # KRdwJRYVcvXwrh493nPqz6L4P/WKqbsH9lWu69vJHcpupijrXtB+KTeq49ICKYBV # RhisLlABXVVMbBRz+wODun01DchgJ7135dN7rLjLRYOzuM7jZO2i0vdH4nHSlUyJ # JofXe9mQDaRV3ikHVolx9UOTpDdP83bbUnP7p0jzQ9dusPu669IwgNzMA3qbF2kV # gmCctGcrLGwW1+3lrm/rJ9rCk3RwlCjwS9gmuecudZk3Z5PCckeSOAmHic30v7Ui # oyTV3yTwVKpdwWR5eeQDfYUI2p4wcVTivF59AUcLPZgRz6GCF5cwgheTBgorBgEE # AYI3AwMBMYIXgzCCF38GCSqGSIb3DQEHAqCCF3AwghdsAgEDMQ8wDQYJYIZIAWUD # BAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoD # ATAxMA0GCWCGSAFlAwQCAQUABCBaU/zxr0ffa1hX5M+s+8Hz8ck8+D7OZzVAaxII # 7DTfhQIGaefB+1SWGBMyMDI2MDUwMzE0MzExMC45NzlaMASAAgH0oIHRpIHOMIHL # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxN # aWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRT # UyBFU046MzcwMy0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0 # YW1wIFNlcnZpY2WgghHtMIIHIDCCBQigAwIBAgITMwAAAh86cGnkojAulQABAAAC # HzANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAe # Fw0yNjAyMTkxOTM5NTFaFw0yNzA1MTcxOTM5NTFaMIHLMQswCQYDVQQGEwJVUzET # MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmlj # YSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046MzcwMy0wNUUw # LUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLO8XFOcfGqAqgiz0+AmQmFl3d # Z0aTG4UFJkqqNdMHy28DaheCBs6ONufukye5x42CWkzgRIy9kE2VWwEntZ8Zkgyr # ykC0bIqsID7+6FxguseTXf1Vwvm1D8104VmetoBJlJ4uGbuyJZUvXDx55nVh50yg # LTzZ24WkQsnPpvRZv2kPc39f3bhLyHVtnHsa/W/86Vrftd+AfFveA+qN/EY+XGj5 # c/DPMXCYECb0arYb92dDJWtwzpyBrp4gfHlgY1UEpc4l4AGELrf2J4wrxTzTW+SM # 8XhV1dOOPrYjD080IbZqL8B+IF0RCdn269YXrGK6QIHipznKZcCS8jN30YAHnTJV # N5Zzs6t/2YsqBGDquvDad7934FFTwzvUcO3VoIyd93XWwvP8/SCFVJh21W8oGQTp # tGHyly+Fl4henVMVZF1v6osOtirX8GFTiEhnf8nRdOg7yZYAJ0xy9CtDfbXaTn/c # f3Lq3N/GCYKFjC+5mUCE+AJhmxMuMdvSUGmKiAFdiPAjUTqsWWBBZJm0eCwgeGJF # mmQA+V7/98BKcE+gUL7O9eWRDQwKeAcvo6rxNv2Y4jKrHA6Z/wi3a/fKUhLCNZES # 8qGdrpDAm7qh+6FjYxytAbkiKM6uTNy/ULPlwtlYZoAJDDQP7eYCywwVbNTbHXRB # SS+NccC0sSB4W7U67wIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFNk72sGDlH0r5Dwv # fGR5XwJI8B7bMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1Ud # HwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js # L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggr # BgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIw # MTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgw # DgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQBlbu3IoynnPz0K1iPb # eNnsej2b15l5sdl2FAFBBGT9lRdc2gNV8LAIusPYHHhUvRDcsx4lbMNhVKPGu4TD # LaqNt/CI+SFtGuqdRLpVP1XE9cCLyKrKPpcJFJCqPpV+efoAtYBmIUQcxxwT7WIQ # 7gag8+rkKvrMkCoRqKS0mKv8J1sKfi85+G2uhZ/1RteSVdYZOZOj+Sb4wzonTCTj # 7EtgMN/BX35W5dTzd7wJdGepYkVi871dSrC2Tr1ZFzAR7S44drCWZpJ6phJabVNO # sNxFJKgSykugOGWzQ318Rr3MTPg2s3Bns+pUPVgMijd4bUOH2BlEsLMMwOcolTTZ # qg1HYrdY1jxpUAI9ipjBQRINL/O705Z+/f2LjNmJQooCVJVX24adpZ519SsfazGo # qXGt91bmqKo0fI09Il4sUHh4ih6rpiQDBlyL7vmvCejwVxYevY4qVwTZ/o3gvl+R # 0lFxYS9feIM4NeG0+WsDZ7jLci5MFeuNwosQY3z26Xg1oj0U9u+ncR9uTU+xBmJ8 # BtlCdhQ13RNMX5P+krRYPB3XCp9Jm6XaO1995q32AIZm1mzBGI6yHlviXaEC5TzG # iO1LXuPtXZU2X93oQJbMoe3v8+5CPKrQalGWyYuh2a3V1pwbj+W0FEmEFPpu8TI+ # qYO1IIQWUSRvFjXth5Ob02hMMjCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkA # AAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl # IEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVow # fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd # TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX # 9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1q # UoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8d # q6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byN # pOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2k # rnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4d # Pf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgS # Uei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8 # QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6Cm # gyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzF # ER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQID # AQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQU # KqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1 # GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 # bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA # QTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbL # j+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1p # Y3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0w # Ni0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIz # LmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwU # tj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN # 3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU # 5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5 # KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGy # qVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB6 # 2FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltE # AY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFp # AUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcd # FYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRb # atGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQd # VTNYs6FwZvKhggNQMIICOAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg # T3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjM3MDMtMDVFMC1E # OTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEw # BwYFKw4DAhoDFQBLIMg1P7sNuCXpmbH2IXT2tXeEEKCBgzCBgKR+MHwxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # dCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA7aFn5DAiGA8y # MDI2MDUwMzA2MjEyNFoYDzIwMjYwNTA0MDYyMTI0WjB3MD0GCisGAQQBhFkKBAEx # LzAtMAoCBQDtoWfkAgEAMAoCAQACAhT3AgH/MAcCAQACAhNsMAoCBQDtorlkAgEA # MDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAI # AgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAHq7s9YMgMpIuyTAwWsMxFD0DDmR # QoXeyij+UMPaYdsxa3ei47tU4WE0xqHP+0mYPcDDrbUyiue3JiyjGqyZhs63H39t # kyIRrg787TNyIuzMJH04BSpAsjQL9jKHDPuDN03FtnZFcxLvnFz+i2e1OAQ5Odan # ScUkOnVkC7TLm/DMelMwJm5tfFkMo6hKZS1tLtKyjJBB8ZMZlm+35LeUNJBgFRCA # D0iG1bZFVD09Rf7diPhBQPHI70wqiFkIrPwgHUS8EKHQ1RrMajudvnX/GWgSZH2L # As6VIoh8Xy8inHRClIVPQeQvEclLgJYcJ7qPQRmfh7UZHYThMVUooesH7aYxggQN # MIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ # MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u # MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAh86 # cGnkojAulQABAAACHzANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0G # CyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCC9i4i759s2Wnap1wdKbd9acy8n # uu8AJEnGyRv4WMUKeTCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EILAkCt9W # kCsMtURkFu6TY0P3UXdRnCiYuPZhe3ykLfwUMIGYMIGApH4wfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAIfOnBp5KIwLpUAAQAAAh8wIgQgXDVXUUgM # F2UJ5kLBUeKOgKL/uQDhW3pavs3L2zobM+AwDQYJKoZIhvcNAQELBQAEggIATLjw # P5daKONsxque5sCnbVFWrZmR7j8OxfHZkiZY4mMqZpbumVt4aAiYVgm2XSlt+WQV # 7c6v5qC6EgLvOTRaMVH2q+AmQSADupvns9IN0pFXaeb8r9S/osjiGlBM8pJB43Ty # tK7GpnA0h13Q6CMFFnvHyfAa0lNEnUjN9w3Kqucos6P7uHPMzo3FT2ZDLpNtH9hi # tPx8EoS7JBcUorfJsNSRBg7YdzK1WUTuzh+hrr57cXxZKBoLbvzZ+VH7V5y9ersg # f1KY+FX0PbXq7yV2Kx6UUnZggLqMe/urK5JqU0dcc+09WbMzVLiES2+2En4lUy0K # dzw9FKCNcubcbmiIOpbogCSmH+g1UxPrF6LsoB21HPtljA0W13NcaZJgU9S5s5mi # 168Vv5BsAAtWKY02R7hNCwuWkGbDW+rdjY+LPXVLop4M46fxz8ty/arM9ypfgh0T # R2xGIDOEQws71vlQ3LUIfgSqlr3CM/1Ek8AtSyO1uqFgd1HWkyEweRj8hoqdUkxc # NvPhFRaUKU9PGgDTBhCshGijpq6v5+1PZZIF+qiNmxTjNwq3BDoN8q5gunWkAOhD # 3rK/Va4VcwmPokIIdnv4uCzwOlbCcTONS0yIg8oCX52TKm6M33KaV8eB5fX3Jxxi # HX36iI0hShmUrPHLYf/XIrS+Z9kIicybpKGy8MM= # SIG # End signature block |