Table of Contents

DNS

Par cet exemple du DNS, je souhaite remontrer la différence entre une chaîne de caractères et un objet.

Demande initiale

Supposons que vous ayez à faire énormément de modifications DNS à cause d'un fournisseur qui change de serveur. On vous donne une liste d'enregistrements DNS de type A et il faut les modifier. Comme vous avez les bons réflexes, vous vous lancez dans deux opérations:

  1. Vérifier les données fournies par le demandeur: la confiance n'exclut jamais le contrôle.
  2. Fournir le rapport preCheck à votre commanditaire.

Pour l'exemple, partons de fichier initial suivant:

A_RecordProvider
google.cap1
google.comp1
google.frp2
google.totop3

Le piège

Si on décide d'aborder le défi en utilisant powershell, alors bien des gens seraient tenter de partir ainsi en utilisant nslookup:

dns_v1.ps1
Import-Csv -Path input_dns.csv | foreach {
  nslookup $_.A_Record 8.8.8.8
}

On obtient des choses horribles.

nslookup : Non-authoritative answer:
At line:1 char:1
+ nslookup google.ca 8.8.8.8
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Non-authoritative answer::String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
Server:  dns.google
Address:  8.8.8.8

Name:    google.ca
Addresses:  2607:f8b0:4020:805::2003
	  172.217.13.131

Cela pose les problèmes suivants:

  1. Les résultats s'affichent sur l'écran mais c'est très dur d'en extraire les informations.
  2. nslookup n'est pas une commande Powershell alors on n'obtient pas d'objet adapté à notre requête DNS
  3. Impossible d'utiliser les résultats pour créer notre fichier de preCheck

Le bon outil

Nous allons donc utiliser la commande DNS PowerShell: Resolve-Dns

dns_v2.ps1
Import-Csv -Path input_dns.csv | foreach {
  Resolve-DnsName $_.A_Record -Type A -Server 8.8.8.8
}

Cette fois-ci on obtient quelque chose de beaucoup plus sympa avec des objets que nous allons pouvoir manipuler.

Name                                           Type   TTL   Section    IPAddress                                
----                                           ----   ---   -------    ---------                                
google.ca                                      A      49    Answer     172.217.13.131                           
google.com                                     A      299   Answer     172.217.13.110                           
google.fr                                      A      299   Answer     172.217.13.163                           
Resolve-DnsName : google.toto : DNS name does not exist
At line:2 char:7
+       Resolve-DnsName $_.A_Record -Type A -Server 8.8.8.8
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (google.toto:String) [Resolve-DnsName], Win32Exception
    + FullyQualifiedErrorId : DNS_ERROR_RCODE_NAME_ERROR,Microsoft.DnsClient.Commands.ResolveDnsName

On obtient toujours une exception pour l'enregistrement qui n'existe pas, mais avec un bloc “try” et une redirection de sortie d'erreurs, on va s'en sortir.

dns_v3.ps1
Import-Csv -Path input_dns.csv | foreach {
    $currentLine = $_
    $record = $currentLine.A_Record
    try {
        $result = Resolve-DnsName $record -Type A -Server 8.8.8.8 2> $null
        Write-Host $result.getType().fullname
    } catch {
        Write-Host ("Error with record: {0}" -f $record)
    }   
}

On obtient des objets que nous allons pouvoir manipuler et exporter.

Microsoft.DnsClient.Commands.DnsRecord_A
Microsoft.DnsClient.Commands.DnsRecord_A
Microsoft.DnsClient.Commands.DnsRecord_A
Error with record: google.toto

Name                                           Type   TTL   Section    IPAddress                                
----                                           ----   ---   -------    ---------                                
google.ca                                      A      299   Answer     172.217.13.131                           
google.com                                     A      299   Answer     172.217.13.110                           
google.fr                                      A      299   Answer     172.217.13.163 

Script final

On se rappelle ce que l'on souhaite: prendre tous les enregistrements DNS A demandés et s'assurer qu'il n'y a pas d'erreurs dans la demande du client.

dns_final.ps1
$results = @()
 
Import-Csv -Path input_dns.csv | foreach {
    $currentLine = $_
    $record = $currentLine.A_Record
    try {
        $result = Resolve-DnsName $record -Type A -Server 8.8.8.8 2> $null
        Write-Host $result.getType().fullname
        $exportLine = $result | Select-Object -Property Name,Type,IPAddress
        $exportLine | Add-Member -MemberType NoteProperty -Name "Status" -Value "ok"
    } catch {
        Write-Host ("Error with record: {0}" -f $record)
        $exportLine = New-Object psobject -Property @{
            'Name' = $record;
            'Type' = 'A';
            'IPAddress' = '';
            'Status' = 'ko';
        }
    }   
    $results += $exportLine
}
 
$results | Export-Csv -Path dnsPreCheck.csv -Delimiter "," -Encoding UTF8 -NoTypeInformation

Le résultat permet de mettre en valeur un domaine qui n'a pas d'entrée A connue. C'est ce que l'on souhaitait découvrir.

NameTypeIPAddressStatus
google.caA172.217.13.131ok
google.comA172.217.13.110ok
google.frA172.217.13.163ok
google.totoAko