Problème rencontré
Lors d'un changement complet du plan d'adressage des serveurs d’un datacenter, il était nécessaire de changer les enregistrements DNS. Au delà des enregistrements NS des serveurs DNS, il fallait aussi mettre à jour l'intégralité des enregistrements statiques A et PTR. Il était nécessaire de proposer une solution qui soit simple à mettre en œuvre (peu d’intervention utilisateur), puisque près de 600 enregistrements était à modifier. Il n'était pas faisable de faire cela manuellement.
Solution proposée
Comme indiqué dans l'intitulé, il a été choisi que cette opération serait réalisée par un script Powershell. Actuellement, il y a encore peu de parcs informatique utilisant Powershell 3 avec le module DNS pour Windows 8/2012. Le module DNS fournit par Powershell 3 peut donc seulement être utilisé dans des cas très limités. La solution proposée utilisait les classes WMI. Il s'agissait ensuite de loguer un maximum d'informations pour avoir un maximum de contrôle sur les modifications apportées.
Les classes WMI
Voici un listing des classes WMI pour les enregistrements DNS les plus courants :
- Enregistrements PTR : MicrosoftDNS_PTRType
- Enregistrements A : MicrosoftDNS_AType
- Enregistrements CNAME : MicrosoftDNS_CNAMEType
- Enregistrements MX : MicrosoftDNS_MXType
- Enregistrements NS : MicrosoftDNS_NSType
Récupération d'enregistrements DNS
Voici un exemple de récupération d'un enregistrement A.
On déclare la zone dans laquelle on veut effectuer la recherche.
001 002
|
$DNSZone = "myenterprise.lan"
|
On définit le serveur DNS sur lequel on effectue la recherche.
001 002
|
$DNSServer = "SRVDNS01"
|
On cherche l'enregistrement via l'attribut OwnerName qui est le nom DNS complet.
001 002
|
$OwnerName = "SRV01.$DNSZone"
|
On utilise une requête WMI sur le serveur DNS avec un filtre sur la zone et l'enregistrement à chercher.
001 002 003 004
|
$Record = Get-WMIObject -Computer $DNSServer ` -Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_AType" ` -Filter "ContainerName='$DNSZone' AND OwnerName='$OwnerName'"
|
Si l'on souhaite obtenir toutes les propriétés de cet enregistrement et notamment voir les autres attributs sur lesquels on peut effectuer une recherche il suffit d'appeler la variable : $Record
Mis à jour d'enregistrements DNS :
En reprenant l'enregistrement précédent, on peut rapidement modifier son addresse IP (ou TTL) via la méthode Modify().
001 002
|
$NewRecord = $Record.Modify($Record.TTL, "10.0.1.1")
|
Détecter si un enregistrement est dynamique :
Aussi, il peut être intéressant de ne mettre à jour que les enregistrements statiques. On peut détecter les enregistrements dynamiques via leur timestamp qui n'est pas nulle :
001 002 003 004
|
if($Record.Timestamp -ne 0){ $NewRecord = $Record.Modify($Record.TTL, "$newRecordAddress") }
|
Il suffit donc juste d'utiliser une structure conditionnelle si sinon sur l'attribut timestamp de notre enregistrement DNS.
Exemple avec un enregistrement PTR :
Pour réaliser cette opération on réutilise les variables $DNSServer, $DNSZone et $OwnerName déclarées plus haut et définir la zone où chercher l'enregistrement PTR.
001 002
|
$DNSZonePTR = "10.in-addr.arpa"
|
La syntaxe pour rechercher un enregistrement PTR est similaire. Seuls la classe WMI et le champ de recherche (PTRDomainName au lieu de Ownername).
001 002 003 004
|
$PTRRecord = Get-WMIObject -Computer $DNSServer ` -Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_PTRType" ` -Filter "ContainerName='$ZonePTR' AND PTRDomainName='$OwnerName.'"
|
Attention, il n'est pas possible de modifier l'IP d'un enregistrement PTR, il faut d'abord supprimer l'enregistrement puis le recréer.
Avant, on récupère la TTL pour la réutiliser afin qu'elle soit identique lors du nouvel enregistrement :
001 002
|
$TTL = $PTRRecord.TTL
|
On supprime l'enregistrement DNS en supprimant l'objet WMI
001 002
|
$PTRRecord | Remove-WmiObject
|
On déclare la nouvelle valeur de notre enregistrement. Si IP vaut 10.B.C.D dans la zone "10.in-addr.arpa" alors celui-ci vaudra D.C.B.10.in-addr.arpa
001 002
|
$PTROwnerName = "1.1.0.10.in-addr.arpa"
|
On déclare le type de notre enregistrement, ici PTR :
001 002 003
|
$PTRTypeClass = [WMIClass]"\\$DNSServer\root\MicrosoftDNS:MicrosoftDNS_PTRType" $PTRNewRecord = $PTRTypeClass.CreateInstanceFromPropertyData("$DNSServer.myenterprise.lan",$ZonePTR,$PTROwnerName,$null,$TTL,"$OwnerName.")
|
Le 4ème attribut est dénommé record class : par défaut il s'agit de IN. La valeur à insérer est 1 ou $null.
Exemple sous Powershell v3 avec module DNS :
Pour terminer, voici comment réaliser les mêmes opérations (Récupération/Mis à jour d'enregistrements DNS) avec le module DNS Powershell v3. Il faut posséder un poste sous Windows 8/2012 pour exécuter ses commandes et avoir installé l'outil de gestion des serveurs DNS (via les outils d'administration).
On commence par déclarer la zone, le serveur DNS et le nom de l'enregistrement :
001 002 003 004 005
|
$DNSZone = "myenterprise.lan" $DNSServer = "DNS01" $RecordName = "SERV01" $NewRecordAddress = "10.0.1.1"
|
Le type est renseigné dans le paramètre RRType. Attention, il est important de stocker l'objet dans une variable car nous allons le réutiliser pour le modifier.
001 002 003
|
$Record = Get-DnsServerResourceRecord -ZoneName "$DNSZone" -Name "$RecordName" ` -RRType "A" -ComputerName "$DNSServer"
|
Pour valider les modifications nous aurons besoin de l'enregistrement DNS avant et après sa mise à jour. Il faut donc réaliser une deuxième récupération de l'enregistrement DNS dans une autre variable.
001 002 003
|
$NewRecord = Get-DnsServerResourceRecord -ZoneName "$DNSZone" -Name "$RecordName" ` -RRType "A" -ComputerName "$DNSServer"
|
Ensuite, il faut modifier la propriété qui nous intéresse, ici l'adresse IP.
001 002
|
$NewRecord.RecordData.IPv4Address.IPAddressToString = "$NewRecordAddress"
|
Enfin, on enregistre les modifications en passant les 2 objets (avant et après modification), la zone et le nom du serveur DNS :
001 002 003
|
Set-DnsServerResourceRecord -NewInputObject $NewRecord -OldInputObject $Record -ZoneName "$DNSZone" ` -ComputerName "$DNSServer"
|