# exportDns.ps1 - Export DNS zones and records from Windows AD DNS # Script d'exportation complète DNS pour migration vers Samba4 Write-Host "=== Début de l'exportation DNS Windows AD ===" -ForegroundColor Green # Vérifier que le module DnsServer est disponible try { Import-Module DnsServer -ErrorAction Stop Write-Host "[OK] Module DnsServer chargé avec succès" } catch { Write-Host "[ERREUR] Module DnsServer non disponible. Installer RSAT DNS ou exécuter sur un serveur DNS" -ForegroundColor Red exit 1 } # Créer le répertoire d'export $ExportPath = "C:\temp\dns-export" if (!(Test-Path $ExportPath)) { New-Item -ItemType Directory -Path $ExportPath -Force | Out-Null Write-Host " Répertoire d'export créé: $ExportPath" } # Initialiser les variables d'export $DnsExport = @{ 'ExportDate' = Get-Date -Format "yyyy-MM-dd HH:mm:ss" 'ExportedBy' = $env:USERNAME 'ServerName' = $env:COMPUTERNAME 'Zones' = @() 'Statistics' = @{ 'TotalZones' = 0 'ForwardZones' = 0 'ReverseZones' = 0 'TotalRecords' = 0 } } # ===== EXPORT DES ZONES DNS ===== Write-Host "`n1. Récupération de toutes les zones DNS..." -ForegroundColor Yellow try { $AllZones = Get-DnsServerZone $DnsExport.Statistics.TotalZones = $AllZones.Count Write-Host "[OK] $($AllZones.Count) zones trouvées" foreach ($Zone in $AllZones) { Write-Host " Traitement de la zone: $($Zone.ZoneName)" -ForegroundColor Cyan # Déterminer le type de zone $ZoneType = "Unknown" $IsReverse = $false if ($Zone.ZoneName -like "*.in-addr.arpa" -or $Zone.ZoneName -like "*.ip6.arpa") { $ZoneType = "Reverse" $IsReverse = $true $DnsExport.Statistics.ReverseZones++ } elseif ($Zone.ZoneName -eq "." -or $Zone.ZoneName -eq "..") { $ZoneType = "Root" } elseif ($Zone.ZoneName -like "_*") { $ZoneType = "Service" } else { $ZoneType = "Forward" $DnsExport.Statistics.ForwardZones++ } # Créer l'objet zone $ZoneData = [PSCustomObject]@{ 'ZoneName' = $Zone.ZoneName 'ZoneType' = $ZoneType 'IsReverse' = $IsReverse 'IsPrimary' = $Zone.ZoneType -eq "Primary" 'IsStub' = $Zone.ZoneType -eq "Stub" 'IsForwarder' = $Zone.ZoneType -eq "Forwarder" 'DynamicUpdate' = $Zone.DynamicUpdate.ToString() 'Records' = @() } # ===== EXPORT DES ENREGISTREMENTS ===== try { $Records = Get-DnsServerResourceRecord -ZoneName $Zone.ZoneName -ErrorAction Stop Write-Host " -> $($Records.Count) enregistrements trouvés" foreach ($Record in $Records) { $RecordData = $null $RecordValue = "" # Extraire les données selon le type d'enregistrement switch ($Record.RecordType) { "A" { $RecordValue = $Record.RecordData.IPv4Address.ToString() } "AAAA" { $RecordValue = $Record.RecordData.IPv6Address.ToString() } "CNAME" { $RecordValue = $Record.RecordData.HostNameAlias.ToString() } "MX" { $RecordValue = "$($Record.RecordData.Preference):$($Record.RecordData.MailExchange)" } "NS" { $RecordValue = $Record.RecordData.NameServer.ToString() } "PTR" { $RecordValue = $Record.RecordData.PtrDomainName.ToString() } "SRV" { $RecordValue = "$($Record.RecordData.Priority):$($Record.RecordData.Weight):$($Record.RecordData.Port):$($Record.RecordData.DomainName)" } "TXT" { $RecordValue = $Record.RecordData.DescriptiveText -join " " } "SOA" { $RecordValue = "$($Record.RecordData.PrimaryServer):$($Record.RecordData.ResponsiblePerson):$($Record.RecordData.SerialNumber)" } default { $RecordValue = $Record.RecordData.ToString() } } # Créer l'objet enregistrement $RecordObj = [PSCustomObject]@{ 'Name' = if ($Record.HostName -eq "@") { "@" } else { $Record.HostName } 'Type' = $Record.RecordType.ToString() 'TTL' = $Record.TimeToLive.TotalSeconds 'Value' = $RecordValue 'Timestamp' = if ($Record.Timestamp) { $Record.Timestamp.ToString("yyyy-MM-dd HH:mm:ss") } else { "Static" } } $ZoneData.Records += $RecordObj $DnsExport.Statistics.TotalRecords++ } } catch { Write-Host " Erreur lors de la lecture des enregistrements: $($_.Exception.Message)" -ForegroundColor Yellow } $DnsExport.Zones += $ZoneData } } catch { Write-Host " Erreur lors de la récupération des zones: $($_.Exception.Message)" -ForegroundColor Red exit 1 } # ===== EXPORT VERS FICHIERS ===== Write-Host "`n2. Export vers fichiers..." -ForegroundColor Yellow # Export JSON complet $JsonFile = "$ExportPath\dns_export_complete.json" $DnsExport | ConvertTo-Json -Depth 10 | Out-File -FilePath $JsonFile -Encoding UTF8 Write-Host "[OK] Export JSON: $JsonFile" # Export CSV des zones $CsvZonesFile = "$ExportPath\dns_zones.csv" $DnsExport.Zones | Select-Object ZoneName, ZoneType, IsReverse, IsPrimary, DynamicUpdate, @{Name='RecordCount';Expression={$_.Records.Count}} | Export-Csv -Path $CsvZonesFile -NoTypeInformation -Encoding UTF8 Write-Host "[OK] Export CSV zones: $CsvZonesFile" # Export CSV des enregistrements par zone foreach ($Zone in $DnsExport.Zones) { if ($Zone.Records.Count -gt 0) { $SafeZoneName = $Zone.ZoneName -replace '[<>:"/\\|?*]', '_' $CsvRecordsFile = "$ExportPath\dns_records_$SafeZoneName.csv" $Zone.Records | Export-Csv -Path $CsvRecordsFile -NoTypeInformation -Encoding UTF8 Write-Host " -> Enregistrements zone $($Zone.ZoneName): $CsvRecordsFile" } } # Export BIND format pour zones principales Write-Host "`n3. Export format BIND..." -ForegroundColor Yellow $BindExportPath = "$ExportPath\bind-zones" if (!(Test-Path $BindExportPath)) { New-Item -ItemType Directory -Path $BindExportPath -Force | Out-Null } foreach ($Zone in ($DnsExport.Zones | Where-Object {$_.ZoneType -eq "Forward" -and $_.IsPrimary})) { $SafeZoneName = $Zone.ZoneName -replace '[<>:"/\\|?*]', '_' $BindFile = "$BindExportPath\db.$SafeZoneName" # Créer le fichier de zone BIND $BindContent = @() $BindContent += "; Zone file for $($Zone.ZoneName)" $BindContent += "; Exported from Windows DNS on $(Get-Date)" $BindContent += "; TTL default: 3600" $BindContent += '$TTL 3600' $BindContent += "" # Ajouter les enregistrements foreach ($Record in $Zone.Records) { $Name = if ($Record.Name -eq "@") { "@" } else { $Record.Name } $TTL = if ($Record.TTL -gt 0) { $Record.TTL } else { "3600" } switch ($Record.Type) { "A" { $BindContent += "$Name`t$TTL`tIN`tA`t$($Record.Value)" } "AAAA" { $BindContent += "$Name`t$TTL`tIN`tAAAA`t$($Record.Value)" } "CNAME" { $BindContent += "$Name`t$TTL`tIN`tCNAME`t$($Record.Value)" } "MX" { $MxParts = $Record.Value -split ":" $BindContent += "$Name`t$TTL`tIN`tMX`t$($MxParts[0])`t$($MxParts[1])" } "NS" { $BindContent += "$Name`t$TTL`tIN`tNS`t$($Record.Value)" } "TXT" { $BindContent += "$Name`t$TTL`tIN`tTXT`t`"$($Record.Value)`"" } "SRV" { $SrvParts = $Record.Value -split ":" if ($SrvParts.Count -eq 4) { $BindContent += "$Name`t$TTL`tIN`tSRV`t$($SrvParts[0])`t$($SrvParts[1])`t$($SrvParts[2])`t$($SrvParts[3])" } } } } $BindContent | Out-File -FilePath $BindFile -Encoding UTF8 Write-Host " -> Zone BIND $($Zone.ZoneName): $BindFile" } # ===== SCRIPT D'IMPORT POUR SAMBA ===== Write-Host "`n4. Génération du script d'import Samba..." -ForegroundColor Yellow $ImportScript = "$ExportPath\import_dns_samba.sh" $ImportContent = @() $ImportContent += "#!/bin/bash" $ImportContent += "# Script d'import DNS pour Samba4" $ImportContent += "# Généré automatiquement depuis exportDns.ps1" $ImportContent += "# Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" $ImportContent += "" $ImportContent += "# Vérifier que samba-tool est disponible" $ImportContent += "if ! command -v samba-tool &> /dev/null; then" $ImportContent += " echo 'Erreur: samba-tool non trouvé'" $ImportContent += " exit 1" $ImportContent += "fi" $ImportContent += "" $ImportContent += "# Demander les credentials une seule fois" $ImportContent += "echo '=== Import des zones et enregistrements DNS vers Samba4 ==='" $ImportContent += "echo" $ImportContent += "read -p 'Nom d'\''utilisateur administrateur Samba [Administrator]: ' SAMBA_USER" $ImportContent += "SAMBA_USER=`${SAMBA_USER:-Administrator}" $ImportContent += "" $ImportContent += "echo -n 'Mot de passe pour `$SAMBA_USER: '" $ImportContent += "read -s SAMBA_PASSWORD" $ImportContent += "echo" $ImportContent += "" $ImportContent += "# Vérifier les credentials avant de continuer" $ImportContent += "echo 'Test des credentials...'" $ImportContent += "if ! samba-tool user show '`$SAMBA_USER' --username='`$SAMBA_USER' --password='`$SAMBA_PASSWORD' &>/dev/null; then" $ImportContent += " echo 'Erreur: Credentials invalides ou utilisateur non autorisé'" $ImportContent += " exit 1" $ImportContent += "fi" $ImportContent += "echo '[OK] Credentials validés pour `$SAMBA_USER'" $ImportContent += "echo" $ImportContent += "" $ImportContent += "# Mode dry-run optionnel" $ImportContent += "read -p 'Mode dry-run (afficher les commandes sans les exécuter) ? [y/N]: ' DRY_RUN" $ImportContent += "DRY_RUN=`${DRY_RUN:-N}" $ImportContent += "" $ImportContent += "if [[ '`$DRY_RUN' =~ ^[Yy]`$ ]]; then" $ImportContent += " echo '[INFO] Mode dry-run activé - aucune modification ne sera effectuée'" $ImportContent += " echo" $ImportContent += "fi" $ImportContent += "" $ImportContent += "# Fonction pour exécuter les commandes samba-tool" $ImportContent += "execute_samba_cmd() {" $ImportContent += " local cmd='`$1'" $ImportContent += " if [[ '`$DRY_RUN' =~ ^[Yy]`$ ]]; then" $ImportContent += " echo '[DRY-RUN] `$cmd'" $ImportContent += " else" $ImportContent += " if eval '`$cmd'; then" $ImportContent += " echo ' [OK] `$(echo '`$cmd' | cut -d'\'' '\'' -f5-6)'" $ImportContent += " else" $ImportContent += " echo ' [ERREUR] `$(echo '`$cmd' | cut -d'\'' '\'' -f5-6)'" $ImportContent += " fi" $ImportContent += " fi" $ImportContent += "}" $ImportContent += "" $ImportContent += "echo 'Import des zones et enregistrements DNS vers Samba4...'" $ImportContent += "echo" # Générer les commandes pour chaque zone et enregistrement foreach ($Zone in ($DnsExport.Zones | Where-Object {$_.ZoneType -eq "Forward" -and $_.IsPrimary -and $_.ZoneName -ne "." -and $_.ZoneName -ne ".." -and $_.ZoneName -notlike "_*"})) { $ImportContent += "# Zone: $($Zone.ZoneName)" $ImportContent += "echo 'Traitement de la zone: $($Zone.ZoneName)'" $ImportContent += "create_zone_if_not_exists `"$($Zone.ZoneName)`"" foreach ($Record in $Zone.Records) { if ($Record.Type -eq "A" -and $Record.Name -ne "@" -and $Record.Name -notlike "*._*") { $ImportContent += "execute_samba_cmd 'samba-tool dns add localhost $($Zone.ZoneName) $($Record.Name) A $($Record.Value) --username=`"`$SAMBA_USER`" --password=`"`$SAMBA_PASSWORD`"'" } elseif ($Record.Type -eq "CNAME" -and $Record.Name -notlike "*._*") { $ImportContent += "execute_samba_cmd 'samba-tool dns add localhost $($Zone.ZoneName) $($Record.Name) CNAME $($Record.Value) --username=`"`$SAMBA_USER`" --password=`"`$SAMBA_PASSWORD`"'" } } $ImportContent += "" } $ImportContent | Out-File -FilePath $ImportScript -Encoding UTF8 Write-Host "[OK] Script d'import Samba: $ImportScript" # ===== RÉSUMÉ ===== Write-Host "`n=== RÉSUMÉ DE L'EXPORT DNS ===" -ForegroundColor Green Write-Host "Zones totales exportées : $($DnsExport.Statistics.TotalZones)" Write-Host "Zones directes : $($DnsExport.Statistics.ForwardZones)" Write-Host "Zones inverses : $($DnsExport.Statistics.ReverseZones)" Write-Host "Enregistrements totaux : $($DnsExport.Statistics.TotalRecords)" Write-Host "" Write-Host "Fichiers générés :" Write-Host "- Export complet JSON : dns_export_complete.json" Write-Host "- Zones CSV : dns_zones.csv" Write-Host "- Enregistrements CSV : dns_records_*.csv" Write-Host "- Zones BIND : bind-zones/db.*" Write-Host "- Script import Samba : import_dns_samba.sh" Write-Host "" Write-Host "[OK] Export DNS terminé avec succès dans : $ExportPath" -ForegroundColor Green