Goatee PFE

Blog of Microsoft Premier Field Engineer Ashley McGlone featuring PowerShell scripts for Active Directory.

PowerShell Script To Combine DNS Zones

PowerShell Script To Combine DNS Zones

  • Comments 8
  • Likes

Have you ever wanted to consolidate or merge duplicate primary DNS zones?  This is a common scenario that I find, and usually it is related to reverse zones.  This script functionality is similar to the DNSExporter tool, but it is much simpler to use.  See the script for syntax and notes.

# -----------------------------------------------------------------------------            
# Copy-DNSZone            
# Mr. Ashley McGlone            
# September, 2010            
#            
# This script is designed for situations where you find two primary copies of a            
# DNS zone and need to copy records from one zone into the other so that you            
# have a single copy of all the primary zone data in one location.  It works for            
# both forward and reverse zone.            
#            
# REQUIREMENTS            
# 1.  This script was tested successfully on:            
#      -Windows Server 2008 R2 with PowerShell v2            
#      -Windows Server 2003 R2 SP2 x64 with PowerShell v1            
# 2.  You must have DNS admin and WMI permissions on the servers involved.            
# 3.  The destination zone must exist (ie. It will not create a new destination            
#     zone automatically.)            
#            
# CAVEATS            
# 1.  Duplicate records of the same name will be overwritten and converted from            
#     aging to static.  TimeStamp is a read-only property.            
# 2.  Copied DNS records will be static (no aging data copied) and their            
#     permissions will be reset (no ACLs copied).            
# 3.  Currently the script only support record types A, CNAME, MX, SRV, PTR.            
#     Feel free to modify the script for other record types as needed.            
# 4.  The script does not copy deligated sub-domains within a zone.            
#            
# MORE INFO            
# DNS WMI Classes            
#   http://msdn.microsoft.com/en-us/library/ms682123(v=VS.85).aspx            
# MicrosoftDNS_ResourceRecord Class            
#   http://msdn.microsoft.com/en-us/library/ms682713(VS.85).aspx            
# CreateInstanceFromPropertyData Method of the MicrosoftDNS_AType Class            
#   http://msdn.microsoft.com/en-us/library/ms682178(VS.85).aspx            
#            
# -----------------------------------------------------------------------------            
            
Param (            
    $srcServer,            
    $srcZone,            
    $destServer,            
    $destZone            
)            
            
If ( ($srcServer -eq $null) -or            
    ($srcZone -eq $null) -or            
    ($destServer -eq $null) -or            
    ($destZone -eq $null)            
    ) {            
    Write-Host "
NAME
    Copy-DNSZone

SYNOPSIS
    Copies DNS records from one zone to another.

SYNTAX
    .\Copy-DNSZone SourceServer SourceZone DestinationServer DestinationZone

EXAMPLES
     Forward zone:
      .\Copy-DNSZone dns1.foo.com myzone.com dns2.foo.com myzone.com
     Reverse zone:
      .\Copy-DNSZone dns1.foo.com 1.10.in-addr.arpa dns2.foo.com 1.10.in-addr.arpa
     Reverse zone roll up:
      .\Copy-DNSZone dns1.foo.com 1.10.in-addr.arpa dns2.foo.com 10.in-addr.arpa

DESCRIPTION
    This script is designed for situations where you find two primary copies of a
    DNS zone and need to copy records from one zone into the other so that you
    have a single copy of all the primary zone data in one location.  It works for
    both forward and reverse zone.

RELATED LINKS
    DNS WMI Classes
      http://msdn.microsoft.com/en-us/library/ms682123(v=VS.85).aspx
    MicrosoftDNS_ResourceRecord Class
      http://msdn.microsoft.com/en-us/library/ms682713(VS.85).aspx
    CreateInstanceFromPropertyData Method of the MicrosoftDNS_AType Class
      http://msdn.microsoft.com/en-us/library/ms682178(VS.85).aspx"            
            
    Throw "Insufficient parameters."            
}            
            
# The parent class MicrosoftDNS_ResourceRecord will capture all resource record            
# subclasses in a single call rather than fetching each separately.            
# Filter out NS and SOA records, because we don't want to copy those to the            
# destination zone.            
# Filter on the zone (ContainerName) so that we only get the zone we want.            
# By default WMI will return all records from all zones.            
$src = Get-WMIObject -ComputerName $srcServer -Namespace 'root\MicrosoftDNS' `
       -Class MicrosoftDNS_ResourceRecord | Where-Object { `
       ($_.ContainerName -eq $srcZone) -and `
       ($_.__Class -ne "MicrosoftDNS_NSType") -and `
       ($_.__Class -ne "MicrosoftDNS_SOAType")}            
            
ForEach ($srcRec in $src) {            
            
    # Echo the source record data for logging            
    $srcRec            
            
    $class         = $srcRec.__CLASS          # A, CNAME, PTR, etc.            
    $ownerName     = $srcRec.OwnerName        # Name column in DNS GUI, FQDN            
    $containerName = $srcRec.ContainerName    # Zone FQDN            
    $domainName    = $srcRec.DomainName       # Zone FQDN            
    $ttl           = $srcRec.TTL              # TTL            
    $recordClass   = $srcRec.RecordClass      # Usually 1 (IN)            
    $recordData    = $srcRec.RecordData       # Data column in DNS GUI, value            
            
    # Dynamically create a new record of the appropriate type (class)            
    $destRec = [WmiClass]"\\$destServer\root\MicrosoftDNS:$class"            
                
    # The CreateInstanceFromPropertyData method varies slightly based on the            
    # record type (class).            
    Switch ($class) {            
        MicrosoftDNS_AType {            
            $destRec.CreateInstanceFromPropertyData($destServer, $destZone, `
                $ownerName, $recordClass, $ttl, $recordData)            
        }            
        MicrosoftDNS_CNAMEType {            
            $destRec.CreateInstanceFromPropertyData($destServer, $destZone, `
                $ownerName, $recordClass, $ttl, $recordData)            
        }            
        MicrosoftDNS_MXType {            
            $preference   = $srcRec.Preference            
            $mailExchange = $srcRec.MailExchange            
            $destRec.CreateInstanceFromPropertyData($destServer, $destZone, `
                $ownerName, $recordClass, $ttl, $preference, $mailExchange)            
        }            
        MicrosoftDNS_SRVType {            
            $priority   = $srcRec.Priority            
            $weight     = $srcRec.Weight            
            $port       = $srcRec.Port            
            $destRec.CreateInstanceFromPropertyData($destServer, $destZone, `
                $ownerName, $recordClass, $ttl, $priority, $weight, $port, `
                $domainName)            
        }            
        MicrosoftDNS_PTRType {            
            $PTRDomainName   = $srcRec.PTRDomainName            
            $destRec.CreateInstanceFromPropertyData($destServer, $destZone, `
                $ownerName, $recordClass, $ttl, $PTRDomainName)            
        }            
    }            
}            
            



 

Attachment: Copy-DNSZone.p-s-1.txt

Can you help me?  Yes!

If you would like to have me or another Microsoft PFE visit your company and assist with the ideas presented in this blog post, then contact your Microsoft Premier Technical Account Manager (TAM) for booking information.

For more information about becoming a Microsoft Premier customer email PremSale@microsoft.com.  Tell them GoateePFE sent you.

Sharing Links
Comments
  • What if you want to perserve the ACL's to ensure dynamic updates occur correctly from the computer that created the record (owner)?

  • Hi John,

    That is a great question.  Currently the script will not preserve ACLs.  I'll add that to my list of feature requests.  If you are a Microsoft Premier customer, then we can schedule a time for me to rewrite the script for you to meet all of your needs.  Let me know if you would like to pursue that option.

    If you want to tackle it on your own, then you'll need to do a Get-ACL on the old record and capture that into a variable.  Then you could use Set-ACL to apply the ACE in the variable to the new record after it is created.

    Also, we have new DNS cmdlets now that will make this much easier.  See the DNSClient and DNSServer modules in the Windows Server 2012 RSAT for a full list of cmdlets.

    Hope this helps,

    GoateePFE

    Ashley McGlone

  • Ashley, I'm working with the account team regarding the premier support. I do believe the account has it, or atleast the company I work for has it (we are a partner with MS... can discuss details elsewhere). How do I get you engaged?

  • Hi John, Give my name to your TAM (Technical Account Manager). They can contact me internally. Ashley

  • OK will do. Thank you

  • When I run the script it takes a long time to run and eventually dies with the error: Get-WMIObject : Quota violation I'm only trying to copy one reverse DNS zone. Any ideas?

  • How large is the zone? WMI for DNS is known not to scale well. The newer cmdlets for DNS work much better.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment