Tuesday, August 10, 2021

Script to Update DNS Record Permissions

 When you have secure dynamic update configured for DNS zones, the individual DNS records are protected by security permissions. The host records are typically secured by the associated computer account. The PTR records are typically secured by the DHCP server account or the associated computer account depending on whether it's a static or dynamic IP address.

If you have highly available DHCP servers, they should be configured with a user account for dynamic DNS updates. This user account is used by both DHCP servers to ensure that records created by one DHCP server can be updated by the other.

If you have highly available DHCP and don't use a shared account, then you'll see errors in the DHCP event log (Event ID 20322) indicating that the DNS record couldn't be updated. After you configure the shared account, the permissions on the DNS records will still be incorrect. The following script adds Full Control permissions on A and PTR records for the shared account. This allows the properly configured DHCP servers to update existing records.

You'll need to do some editing on this script for your environment:

  • $DynamicDnsUser needs to be set to your shared user account.
  • $Server needs to be set to the name of your DNS server.
  • $zones needs to contain the zones you want to modify. 

#DynamicDnsUser is the user configured on both DHCP servers for dynamic DNS
#This uses the SamAccountName of the user
$DynamicDnsUser = Get-ADUser ddnsuser

#Query the SID for this user and create a ACE allowing full control
$SID = New-Object System.Security.Principal.SecurityIdentifier $DynamicDnsUser.SID.Value
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $SID, "GenericAll", "Allow"

#When running DNS cmdlets from a workstation
#you need to specify the server you are acting on
$server = "DNSServer"

#query a list of all zones to loop through and set permissions
#$zones = Get-DnsServerZone -ComputerName $server
#$zones = $zones | where ZoneType -eq Primary

$zones = Get-DnsServerZone "40.10.in-addr.arpa"

Foreach ($zone in $zones) {

    #Query all records in the zone
    #Record type ensures that the get the correct type of records
    #based on forward or reverse lookup zones
    If ($zone.IsReverseLookupZone -eq $true) {
        $recordType = "PTR"
    } Else {
        $recordType = "A"
    }

    $records = Get-DnsServerResourceRecord -ComputerName $server -ZoneName $zone.ZoneName -RRType $recordType

    #Loop through all records in the zone and add
    #the ACE for the dynamic DNS user
    #Need to set the location to AD: for the *-ACL cmdlets to work
    Foreach ($record in $records) {

        Push-Location -Path AD:
        $ACL = Get-Acl -Path $record.DistinguishedName
        $ACL.AddAccessRule($ACE)    
        $ACL | Set-Acl -Path $record.DistinguishedName    
        Pop-Location

    } #end foreach records

} #end foreach zones

Please be aware this only works to allow the DHCP server to update the DNS records. In most organizations, the host records are dynamically updated by the individual computers. If you want to add the correct computer account to a DNS record, then you need to approach this differently.

The following link has a script that finds a computer account that matches a host record and assigns permissions to that computer account. This script was used as a starting point for my script above.