Tuesday, December 27, 2016

Fixing dns record permissions for dynamic dns

In case you have dns records that need to be changed from static to dynamic, or the machine/clusters that will be updating them have changed, you can modify the dns record permissions to allow updates.  Doing this through the gui is fine for a few records, but if you need something a bit more simple and automated, you can try this script.  It takes both the computer name (doesn't have to match the dns record, just needs to be a computer object), and the dns record (fqdn) that you are updating.  This script will work for AD dns only, and would be limited to the current domain, and likely any forest wide partitions.  If you check my article on managing other domains in powershell, you can probably get edits to other domains working on this with a few modifications and extra parameters.



param (
  $computername,
  $dnsrecord
)

$script:computernameSam = $computername + "$"

try {
  import-module activedirectory
} catch {
  write-error "This script requires the AD powershell module"
  exit
}
while ( (test-path -path Ad:) -ne $true  )
{
  start-sleep -seconds 2
}

#Standard ACL for a dynamic dns entry
  #ActiveDirectoryRights : CreateChild, DeleteChild, ListChildren, ReadProperty, DeleteTree, ExtendedRight, Delete,
  #                        GenericWrite, WriteDacl, WriteOwner
  #InheritanceType       : None
  #ObjectType            : 00000000-0000-0000-0000-000000000000
  #InheritedObjectType   : 00000000-0000-0000-0000-000000000000
  #ObjectFlags           : None
  #AccessControlType     : Allow
  #IdentityReference     : Domain\machine$
  #IsInherited           : False
  #InheritanceFlags      : None
  #PropagationFlags      : None
# 

function get-partition {
  param ( $record )
  #need to split off everything after first name to find longest zone match
  #using get-dnsserverzone ($name)
  
  $dnsrecordparts = $record.split(".")
  
  for ($i = 1; $i -lt $dnsrecordparts.length; $i++) {
    $zonenameTest = $dnsrecordparts[$i..($dnsrecordparts.length -1)] -join "."
    $zoneObj = get-dnsserverzone $zonenameTest -ea 0
    if ($zoneObj -ne $null) {
    write-output -inputobject $zoneobj
    $i = $dnsrecordparts.length + 1
    }
  }
  
}

function get-dnsobject {
  param ($record)
  $zoneObject = get-partition -record $record
  if ($zoneObject -ne $null) {
    $zonename = $zoneObject.zonename
    $record -match "(.*)(\.$zonename)"
    $dnsRecordDN = "dc=" + $matches[1] + "," + $zoneobject.distinguishedname
     try {
       get-adobject  $dnsRecordDN
    } catch { Throw "Unable to find dns record for this machine"}
  } else { throw "DNS zone not found"}
}

try {
  try {
    $guid = [guid]'00000000-0000-0000-0000-000000000000'
    $adcomputer = get-adcomputer $computername -property objectsid
    $sid = $adcomputer.objectsid
    $ctrl = [System.Security.AccessControl.AccessControlType]::Allow
    $rights = 983423
    $intype =[System.DirectoryServices.ActiveDirectorySecurityInheritance]::None
    $rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($sid,$rights,$ctrl,$guid)
  } catch { throw "Unable to get computer account SID" }

  try {
    #find record
    $dnsDN = get-dnsObject -record $dnsrecord
  } catch { throw $_ }
  
  try {
    $acl = get-acl ad:"$($dnsDN.distinguishedname)"
    $acl.setowner([system.security.principal.ntaccount]"$script:computernameSam")
    $acl.AddAccessRule($rule)
    Set-Acl -acl $acl -path ad:"$($dnsDN.distinguishedname)"
  } catch { throw $_ }

} catch { $_}

No comments:

Post a Comment