This is an old revision of the document!
Table of Contents
DNS
Here I want to show how huge the difference is between a string and an object.
Initial request
To start, let's suppose you have to perform a lot of DNS modifications because a service provider of yours has changed IP server. Since you are wise, you are going to follow the rule: Trust but verify.
- Check input: maybe some mistakes in the request
- Provide a preCheck report to the requester
This is the example we are going to deal with:
| A_Record | Provider | 
|---|---|
| google.ca | p1 | 
| google.com | p1 | 
| google.fr | p2 | 
| google.toto | p3 | 
Trap to avoid
Sysadmins are used to execute nslookup command to query DNS servers. Let's put it into a powershell script.
- dns_v1.ps1
- Import-Csv -Path input_dns.csv | foreach { nslookup $_.A_Record 8.8.8.8 } 
Output is a nightmare.
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
Here is an issues list:
- Quite difficult to parse results
- nslookup is not a built-in Powershell command, as a result we don't get answer as kind of DNS object
- Really hard to create preCheck output file
the right tool for the right problem
Recent versions of PowerShell includes the perfect command for this request: Resolve-Dns.
- dns_v2.ps1
- Import-Csv -Path input_dns.csv | foreach { Resolve-DnsName $_.A_Record -Type A -Server 8.8.8.8 } 
Now script outputs something we can easily manage and export.
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
We still raise an exception from google.toto record. We are going to use a try-catch block to handle this.
- 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) } } 
When the DNS A record exists, we get an object from Microsoft.DnsClient.Commands.DnsRecord_A class. Otherwise we catch the exception properly.
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
Final script
Reminder: we want to verify if all DNS A records provided by the requester are correct.
- 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 
From the result we can easily identify names without DNS A records. Mission accomplished 
| Name | Type | IPAddress | Status | 
|---|---|---|---|
| google.ca | A | 172.217.13.131 | ok | 
| google.com | A | 172.217.13.110 | ok | 
| google.fr | A | 172.217.13.163 | ok | 
| google.toto | A | ko | 
