I am trying to bulk edit DNS TTL in Windows Server DNS using PowerShell. What I really can't wrap my head around is the absence of any FQDN in Record Objects I get from Get-DnsServerResourceRecord
.
My DNS setup has a primary zone and many subdomains.
primaryzone.tld
├── sub1
│ ├── record1
│ ├── record2
│ └── subsub1
│ ├── (same as parent)
│ ├── record1.1
│ └── record2.1
├── sub2
└── sub3
As there is no possibility to recurse with Get-DnsServerResourceRecord
I have to loop over the subdomains, which I can not gather programatically, to get all records, not just the ones on the root-level of the zone:
$DNSServer = "dc.company.tld"
$Zone = "primaryzone.tld"
$ChildZone = "sub1"
$SubDomains = @("","subsub1")
ForEach ($SubDomain in $SubDomains){
if ( $SubDomain -ne "" ) {
$FullDomain = "$($SubDomain).$($ChildZone)"
}
else {
$FullDomain = $ChildZone
}
Get-DnsServerResourceRecord -ComputerName $DNSServer -ZoneName $Zone -Name "$($FullDomain)"
Is this really supposed to be that way?
If I now want to change TTL for all records under subsub1
I try it like this:
Get-DnsServerResourceRecord -ComputerName $DNSServer -ZoneName $Zone -Name "$($FullDomain)" |
ForEach-Object{
$newRecord = $_.Clone()
$newRecord.TimeToLive = $ttl
Set-DnsServerResourceRecord -ComputerName $DNSServer -NewInputObject $newRecord -OldInputObject $_ -ZoneName $Zone
}
Which works for the subsub1 (same as parent)
record, that has a HostName
property of subsub1.sub1
thus giving a full path inside the primaryzone.tld
. Whereas the record1.1
has a HostName
of record1.1
stripping it of any information regarding its position in the tree. This results in this error:
Set-DnsServerResourceRecord : Resource record in OldInputObject not found in primaryzone.tld zone on dc.company.tld server.
At C:\Users\me\Desktop\dns_ttl.ps1:24 char:13
+ Set-DnsServerResourceRecord -ComputerName $DNSServer -NewInputObject ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (dc.company.tld:root/Microsoft/...rResourceRecord) [Set-DnsServerResourceRecord], CimException
+ FullyQualifiedErrorId : WIN32 9714,Set-DnsServerResourceRecord
I interpret this as the Set-DnsServerResourceRecord
not finding the OldInputObject
record because it has no clue where to look, except in the root-level of the zone.
Why can I specify -Name subdomain
for Get-DnsServerResourceRecord
but when writing it back with Set-DnsServerResourceRecord
it does not take a -Name
argument? Why don't record objects not contain any info on their absolute (FQDN) position in the zone?
How can something so simple be so hard?
EDIT:
I changed my script according to the suggestions by @Cpt.Whale
$DNSServer = "dc.company.tld"
$TargetZone = "primary.tld"
$TTL = [System.TimeSpan]::FromMinutes(1)
$SubDomain = "sub.primary.tld"
$Zones = Get-DnsServerZone -ComputerName $DNSServer | Where {
$_.ZoneType -eq 'Primary' -and
$_.IsReverseLookupZone -eq $false -and
$_.ZoneName -ne 'TrustAnchors' -and
$_.ZoneName -eq $TargetZone
}
Foreach ($DnsZone in $Zones) {
# Get all records in zone by not specifying -Name:
$Records = $DnsZone | Get-DnsServerResourceRecord -ComputerName $DNSServer
$Records | Foreach {
if ($_.HostName -match "$SubDomain$") {
if ($_.TimeToLive -ne $TTL) {
# This weird copy is due to awkward CIM references
$oldRecord = $_
$newRecord = $_.Clone()
$newRecord.TimeToLive = $TTL
# Update the TTL on the existing record:
Set-DnsServerResourceRecord -ComputerName $DNSServer -Old $oldRecord -New $newRecord -ZoneName $DnsZone.ZoneName
# Report changes
"{0,-50} TTL changed from {1,12} to {2,12}" -f $_.HostName, $_.TimeToLive, $TTL
}
}
}
}
With this I get full HostName
, but still the Error I described above
the DNS record-type cim object doesn't have a ZoneName
property, but it does keep the subdomain - it's part of the HostName
of the record. DNS barely cares about subdomains at all unless they are a separate zone.
Something to start with is double-checking whether you've actually got only one zone:
$zones = Get-DnsServerZone -ComputerName $DNSServer | Where {
$_.ZoneType -eq 'Primary' -and
$_.IsReverseLookupZone -eq $false -and
$_.ZoneName -ne 'TrustAnchors'
}
$zones
Then, for example:
$TTL = [System.TimeSpan]::FromHours(2) ## example TTL
Foreach ($DnsZone in $Zones) {
# Get all records in zone by not specifying -Name:
$records = $DnsZone | Get-DnsServerResourceRecord -ComputerName $DNSServer
$records | Foreach {
# This weird copy is due to awkward CIM references
$old = $_
$new = $_.Clone()
$new.TimeToLive = $TTL
# Update the TTL on the existing record:
Set-DnsServerResourceRecord -ComputerName $DNSServer -Old $old -New $new -ZoneName $DnsZone.ZoneName
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.