Tester l'intégrité du domaine racine sur tous les serveurs DNS

Microsoft.Windows.DNSServer.2016.Task.HealthCheck.RootDomainAcrossAllDnsServers (Task)

Teste la disponibilité pour chaque domaine sur chaque serveur DNS. Indiquez les noms de serveurs remplaçant Parameter1 et les noms de domaine avec Parameter2. Non pris en charge sur Nano.

Element properties:

TargetMicrosoft.Windows.DNSServer.2016.Healthcheck.TaskTarget
AccessibilityInternal
CategoryCustom
EnabledTrue
RemotableFalse
Timeout300

Member Modules:

ID Module Type TypeId RunAs 
PA ProbeAction Microsoft.Windows.DNSServer.2016.ParametrizedPowershellProbe.PA Microsoft.Windows.DNSServer.2016.ActionAccount

Source Code:

<Task ID="Microsoft.Windows.DNSServer.2016.Task.HealthCheck.RootDomainAcrossAllDnsServers" Accessibility="Internal" Target="Microsoft.Windows.DNSServer.2016.Healthcheck.TaskTarget" Enabled="true" Timeout="300" Remotable="true">
<Category>Custom</Category>
<ProbeAction ID="PA" TypeID="Microsoft.Windows.DNSServer.2016.ParametrizedPowershellProbe.PA" RunAs="Microsoft.Windows.DNSServer.2016.ActionAccount">
<ScriptName>Microsoft.Windows.Server.10.0.HealthCheck.RootDomainAcrossAllDnsServers.Task.Script.ps1</ScriptName>
<ScriptBody><Script>

param ([String] $PrincipalName, [String] $Parameter1, [String] $Parameter2, [String] $Parameter3)
$SCRIPT_NAME = "HealthCheckRootDomainAcrossAllDnsServersServer10.0"

$global:stringOutput = "Messages: "
$global:htmlReport = ""

try
{
Enum RetStatus
{
Success
Failure
RpcServerIsUnavailable
AccessIsDenied
ZoneDoesNotExist
OperationIsNotSupported
RecordDoesNotExist
NotApplicable
ResolveDnsNameServerNotFound
ResolveDnsNameResolutionFailed
ResolveDnsNameTimeoutPeriodExpired
}


Enum ValidationType
{
Domain
Zone
ZoneAging
ZoneDelegation
Forwarder
RootHints
}
}
catch
{

}

$script:resultView =@{
"List" = "List"
;"Table" = "Table"
}

Function LogComment
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$message,

[int]$level = $script:logLevel.Verbose
)

#$stringBuilder.AppendLine($message);
$global:stringOutput += "`r`n" + $message
}

Function ExecuteCmdLet
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$cmdLetName,
[HashTable]$params = @{}
)
$cmdString=$cmdLetName;
$displayString=$cmdLetName;
$script:cmdLetReturnedStatus = [RetStatus]::Success;
if ($null -ne $params) {
foreach($key in $params.keys) {
if ($script:switchParamVal -eq $params[$key]) {
$cmdString +=" -$key ";
$displayString +=" -$key ";
} else {
$cmdString += " -$key `$params[`"$key`"]";
$displayString += " -$key $($params[$key])";
}
}
}
$cmdString += " -ErrorAction Stop 2&gt; `$null";
$displayString += " -ErrorAction Stop 2&gt; `$null";
LogComment $displayString $script:logLevel.Host;
$retObj = $null;
try {
$retObj = Invoke-Expression $cmdString;
} catch [Exception] {
if (Get-Member -InputObject $_.Exception -Name "Errordata")
{
# Handling DNS server module specific exceptions.
if (5 -eq $_.Exception.Errordata.error_Code) {
LogComment $("Caught error: Access is denied, considering it as current login creds don't have server read access.") $script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::AccessIsDenied;
} elseif (1722 -eq $_.Exception.Errordata.error_Code) {
LogComment $("Caught error: The RPC server is unavailable, considering it as server is down.") `
$script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::RpcServerIsUnavailable;
} elseif (9601 -eq $_.Exception.Errordata.error_Code) {
LogComment $("Caught error: DNS zone does not exist, considering it as given server isn't hosting input zone.") $script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::ZoneDoesNotExist;
} elseif (9611 -eq $_.Exception.Errordata.error_Code) {
LogComment $("Caught error: Invalid DNS zone type, considering it as we can't perform current operation on input zone.") $script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::OperationIsNotSupported;
} elseif (9714 -eq $_.Exception.Errordata.error_Code) {
LogComment $("Caught error: DNS name does not exist, considering it as input record doesn't exist.") `
$script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::RecordDoesNotExist;
} else {
LogComment $("Caught error while executing '" + $displayString + "' with errorcode: " + $_.Exception.Errordata.error_Code) $script:logLevel.Error;
$script:cmdLetReturnedStatus = $([String]$_.Exception.Errordata.error_Code + ":" + $_.Exception.Errordata.error_WindowsErrorMessage);
#throw;
}
} elseif (Get-Member -InputObject $_ -Name "FullyQualifiedErrorId")
{
# Handling Resolve-DnsName specific errors.
if ($_.FullyQualifiedErrorId.Contains("DNS_ERROR_RCODE_NAME_ERROR")) {
LogComment $("Caught error: ResolveDnsNameResolutionFailed in Resolve-DnsName.") $script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::ResolveDnsNameResolutionFailed;
} elseif ($_.FullyQualifiedErrorId.Contains("System.Net.Sockets.SocketException")) {
LogComment $("Caught error: ResolveDnsNameServerNotFound in Resolve-DnsName.") $script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::ResolveDnsNameServerNotFound;
} elseif ($_.FullyQualifiedErrorId.Contains("ERROR_TIMEOUT")) {
LogComment $("Caught error: ResolveDnsNameTimeoutPeriodExpired in Resolve-DnsName.") $script:logLevel.Warning;
$script:cmdLetReturnedStatus = [RetStatus]::ResolveDnsNameServerNotFound;
} else {
LogComment $("Caught error while executing '" + $displayString + "' `n" + $_.Exception) $script:logLevel.Error;
$script:cmdLetReturnedStatus = $([String]$_.FullyQualifiedErrorId + ":" + $_.Exception);
throw;
}
} else
{
LogComment $("Caught error while executing '" + $displayString + "' `n" + $_.Exception) $script:logLevel.Error;
$script:cmdLetReturnedStatus = $($_.Exception);
throw;
}
}
if ($null -eq $retObj) {
LogComment "CmdLet returned with NULL..." $script:logLevel.Host;
}
return $retObj
}

Function Insert-ResultInObject
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[Object]$inputObj,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]$resultName,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]$resultVal
)
if (Get-Member -InputObject $inputObj -Name $resultName) {
$inputObj.$resultName = $resultVal;
} else {
$inputObj | Add-Member -memberType NoteProperty -name $resultName -value $resultVal;
}
return $inputObj;
}

Function Generate-Report
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[Object]$inputObj,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]$contextName,
[String]$viewAs = $script:resultView.Table
)

$head = @'
&lt;!--mce:0--&gt;
'@

$header = "&lt;H1&gt;DNS Health Report for " + $contextName + "&lt;/H1&gt;";
$ouputFile = $contextName + ".html";
$inputObj = $inputObj | ? {$null -ne ($_ | gm -m properties)};
$report = $inputObj | ConvertTo-Html -Head $head -Body $header -As $viewAs

# Do the colour coding of Success &amp; Failure, basically a hack in HTML.
$success2Search = "&lt;td&gt;" + [RetStatus]::Success + "&lt;/td&gt;";
$success2Replace = "&lt;td style=`"color:green;font-weight:bold;`"&gt;" + [RetStatus]::Success + "&lt;/td&gt;";
$failure2Search = "&lt;td&gt;" + [RetStatus]::Failure + "&lt;/td&gt;";
$failure2Replace = "&lt;td style=`"color:red;font-weight:bold;`"&gt;" + [RetStatus]::Failure + "&lt;/td&gt;";

$report = $report -creplace $success2Search, $success2Replace;
$report = $report -creplace $failure2Search, $failure2Replace;

$global:htmlReport += $report
}

#
# Tests whether given DNS Server is able to resolve input DNS Name.
#
Function Test-DnsServerForInputDnsName
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$dnsName,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$dnsServer,
$rrType = "All"
)
$result = [RetStatus]::Failure;

try {
$retObj = ExecuteCmdLet "Resolve-DnsName" @{"Name" = $dnsName; "Type" = $rrType; "Server" = $dnsServer};
if ($null -eq $retObj) {
LogComment $("Resolve-DnsName for " + $dnsName + " failed on server " + $dnsServer + " with " + $script:cmdLetReturnedStatus) $script:logLevel.Error;
$result = $script:cmdLetReturnedStatus;
} else {
LogComment $("Name resolution of " + $dnsName + " passed on server " + $dnsServer);
$result = [RetStatus]::Success;
}

} catch {
LogComment $("Test-DnsServerForInputDnsName failed " + $_.Exception) $script:logLevel.Error;
$result = [RetStatus]::Failure;
}

return $result;
}

Function Test-DnsServerForInputZone
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$zoneName,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$dnsServer,
$remoteServer = "."
)
$result = [RetStatus]::Failure;

try {

$dnsServerIP = $null;
if (![Net.IPaddress]::TryParse($dnsServer, [ref]$dnsServerIP)) {
try {
#Resolve and get first IP
$dnsServerIP = [System.Net.Dns]::GetHostAddresses($dnsServer).IPAddressToString.Split(" ")[0];
} catch {
LogComment $("Exception while trying to get IP Address of " + $dnsServer + "`n" + $_.Exception) $script:logLevel.Error;
throw;
}
}

$retObj = ExecuteCmdLet "Test-DnsServer" @{"ComputerName" = $remoteServer; "ZoneName" = $zoneName; "IPAddress" = $dnsServerIP};
if ($null -eq $retObj) {
LogComment $("Test-DnsServer failed for " + $zoneName + " on server " + $dnsServer) $script:logLevel.Warning;
$result = $script:cmdLetReturnedStatus;
} else {
if (($retObj.Result -eq "Success") -or ($retObj.Result -eq "NotAuthoritativeForZone")) {
LogComment $("Test-DnsServer passed for " + $zoneName + " on server " + $dnsServer + " with Result: " + $retObj.Result);
$result = [RetStatus]::Success;
} else {
LogComment $("Test-DnsServer failed for " + $zoneName + " on server " + $dnsServer + " with Result: " + $retObj.Result) $script:logLevel.Warning;
$result = $retObj.Result;
}
}
} catch {
LogComment $("Test-DnsServerForInputDnsName failed " + $_.Exception) $script:logLevel.Error;
$result = [RetStatus]::Failure;
}

return $result;
}

Function Test-DnsServerForInputContext
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$dnsServer,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$context,
$remoteServer = "."
)
$result = [RetStatus]::Failure;

try {

$retObj = ExecuteCmdLet "Test-DnsServer" @{"ComputerName" = $remoteServer; "IPAddress" = $dnsServer; "Context" = $context};
if ($null -eq $retObj) {
LogComment $("Test-DnsServer failed for DnsServer: " + $dnsServer + " with context: " + $context) $script:logLevel.Warning;
$result = $script:cmdLetReturnedStatus;
} else {
if ($retObj.Result -eq "Success") {
LogComment $("Test-DnsServer Passed for DnsServer: " + $dnsServer + " with context: " + $context + " and Result: " + $retObj.Result);
$result = [RetStatus]::Success;
} else {
LogComment $("Test-DnsServer Failed for DnsServer: " + $dnsServer + " with context: " + $context + " and Result: " + $retObj.Result) $script:logLevel.Warning;
$result = $retObj.Result;
}
}
} catch {
LogComment $("Test-DnsServerForInputContext failed " + $_.Exception) $script:logLevel.Error;
$result = [RetStatus]::Failure;
}

return $result;
}

Function Get-HashtableFromString
{
param(
[string] $serializedHashtable
)

[Hashtable] $ht = New-Object -TypeName Hashtable

$kvStrings = $Parameter1 -split ";"

foreach($kvStr in $kvStrings)
{
if($kvStr -ne $null -and $kvStr -ne "")
{
$arr = $kvStr -split ","

$list = New-Object -TypeName System.Collections.Generic.List[string]
for($i=1;$i -lt $arr.Length; $i++)
{
if($arr[$i] -ne $null -and $arr[$i] -ne "") { $list.Add($arr[$i]) }
}
$ht.Add($arr[0],$list)
}
}

return $ht
}

Function Get-StringFromHashtable
{
param(
[Hashtable] $ht
)

[string]$result = ""

foreach($kv in $ht.GetEnumerator())
{
$result += ";"+ $kv.Key
if($kv.Value -ne $null)
{
foreach($value in $kv.Value)
{
$result += "," + $value
}
}
}

return $result
}

[bool]$isRootZone = $true
if($Parameter1 -eq $null -or $Parameter1 -eq "")
{
Write-Host "Parameter1 for task can not be empty! Please specify required value."
Return
}

if($Parameter2 -eq $null -or $Parameter2 -eq "")
{
Write-Host "Parameter2 for task can not be empty! Please specify required value."
Return
}

$dnsServerList = $Parameter1 -split ";" | Where-Object {$_}
$zoneList = $Parameter2 -split ";" | Where-Object {$_}

[String]$outputReportName = $MyInvocation.MyCommand

$statusArray = @();

foreach($zone in $zoneList) {

$status = New-Object PSObject;
$status | Add-Member -memberType NoteProperty -name "ZoneName" -value $zone;
$zone = $zone+"."
foreach($dnsServer in $dnsServerList) {
try {
$result = [RetStatus]::Success;
$resultStream = $null;

$retVal1 = Test-DnsServerForInputDnsName $zone $dnsServer;
$resultStream = $resultStream + "ResolveDnsName:" + $retVal1 + "`n";
$retVal2 = Test-DnsServerForInputZone $zone $dnsServer $dnsServer;
$resultStream = $resultStream + "TestDnsServer:" + $retVal2 + "`n";

if (!(([RetStatus]::Success -eq $retVal1) -and ([RetStatus]::Success -eq $retVal2))) {
$result = [RetStatus]::Failure;
}

# If it's root zone then validate _msdcs &amp; _ldap infra records
if ($isRootZone) {
$retVal3 = Test-DnsServerForInputDnsName ("_msdcs." + $zone) $dnsServer;
$resultStream = $resultStream + "MsdcsResolveDnsName:" + $retVal3 + "`n";
$retVal4 = Test-DnsServerForInputZone ("_msdcs." + $zone) $dnsServer $dnsServer;
$resultStream = $resultStream + "MsdcsTestDnsServer:" + $retVal4 + "`n";
$retVal5 = Test-DnsServerForInputDnsName ("_ldap._tcp.dc._msdcs." + $zone) $dnsServer "SRV";
$resultStream = $resultStream + "LdapTCPMsdcsResolveDnsName:" + $retVal5 + "`n";
if (!(([RetStatus]::Success -eq $retVal3) -and ([RetStatus]::Success -eq $retVal4) -and ([RetStatus]::Success -eq $retVal5))) {
$result = [RetStatus]::Failure;
}
}

if ([RetStatus]::Success -eq $result) {
LogComment $("Validation of " + $zone + " passed on DNS Server: " + $dnsServer);
LogComment $("Validation of " + $zone + " passed on DNS Server: " + $dnsServer) `
$script:logLevel.Host;
} else {
LogComment $("Validation of " + $zone + " failed on DNS Server: " + $dnsServer) `
$script:logLevel.Error;
LogComment $("Validation output:" + $resultStream) $script:logLevel.Error;
$result = $resultStream;
}
} catch {
LogComment $("Test-ZoneHealthAcrossAllDnsServers failed for Zone: " + $zone + " on DNSServer: " + $dnsServer + " `n " + $_.Exception) `
$script:logLevel.Error;
$result = [RetStatus]::Failure;
}
$status = Insert-ResultInObject $status $dnsServer $result;
}
$statusArray += $status;
}
Generate-Report $statusArray $outputReportName $script:resultView.Table;


$global:htmlReport
</Script></ScriptBody>
<PrincipalName>$Target/Host/Host/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$</PrincipalName>
<Parameter1/>
<Parameter2/>
<Parameter3/>
<TimeoutSeconds>300</TimeoutSeconds>
</ProbeAction>
</Task>