Search code examples
powershelldnsactive-directory

PowerShell: Programmatically deleting AD SRV records that contain any upper case characters


Using PowerShell and running it as an Administrator with Domain Admin credentials, I am trying to programmatically delete AD SRV records containing any upper case characters, rather than clean up these records manually and individually. The problem first appeared with the introduction of Windows Server 2016 into an AD domain that had Windows 2012 (and below) DCs. I've been banging my head trying to revise the code below and worked through wrong RegEx and wrong variables, and now I am at the point where I'm almost to the finish line but the code at this point is reporting that its unable to delete records which match condition of upper case characters. The latest code is below, followed by a snippet of the latest results, and finally, a snippet of the raw data the code is working against. Before you ask, hotfixes to fix this problem on Windows Server 2016 have long been installed as well as Group Policy settings in place to prevent it, however the upper case SRV records still tend to re-insert themselves from time to time and at this point I'm resorting to PowerShell for cleanup. It's a lab anyway, and the task of creating the PowerShell has now become itself the point of the exercise; and I'm fine with that. Any thoughts on where I am going wrong below? Thank you for reading.

Latest Code:

Clear-Host
# DNS zones to examine
$zoneNames = @("_msdcs.alpha.local", "alpha.local")
# DNS server to query
$dnsServer = 'dc2.alpha.local'
# Get all SRV records from the specified zones
$allSrvRecords = foreach ($zoneName in $zoneNames) {
    Get-DnsServerResourceRecord -ZoneName $zoneName -RRType SRV -ComputerName $dnsServer
}
# Array to store deleted records
$deletedRecords = @()

# Iterate through all SRV records
foreach ($record in $allSrvRecords) {
        if ($record.RecordData.DomainName -cmatch '[A-Z]') {
        try { # Attempt to delete the record
            Write-Host "Attempting to delete record: $($record.HostName) in zone $($ZoneName)"
            Remove-DnsServerResourceRecord -Name $record.HostName -RRType $record.RecordType -RecordData $Record.RecordData.DomainName -ZoneName $ZoneName -ComputerName $dnsServer -Force
            $deletedRecords += $record
            Write-Host "Deleted record: $($record.HostName) in zone $ZoneName"
        } catch {
            Write-Host "Error deleting record: $($record.HostName)"
            Write-Host "Error details: $_"
        }
    }
}
# Output results
Write-Host "Deleted records:"
$deletedRecords | ForEach-Object { $_.HostName }

Latest Results Snippet:

Attempting to delete record: _kerberos._tcp.Site1._sites.dc in zone alpha.local
Error deleting record: _kerberos._tcp.Site1._sites.dc
Error details: InputObject for resource record has an invalid value. Failed to remove the resource record on dc2.alpha.local server. Please check extended error for additi
onal details.
Attempting to delete record: _ldap._tcp.Site1._sites.dc in zone alpha.local
Error deleting record: _ldap._tcp.Site1._sites.dc
Error details: InputObject for resource record has an invalid value. Failed to remove the resource record on dc2.alpha.local server. Please check extended error for additi
onal details.
Attempting to delete record: _kerberos._tcp.Site3._sites.dc in zone alpha.local
Error deleting record: _kerberos._tcp.Site3._sites.dc
Error details: InputObject for resource record has an invalid value. Failed to remove the resource record on dc2.alpha.local server. Please check extended error for additi
onal details.
Attempting to delete record: _ldap._tcp.Site3._sites.dc in zone alpha.local
Error deleting record: _ldap._tcp.Site3._sites.dc
Error details: InputObject for resource record has an invalid value. Failed to remove the resource record on dc2.alpha.local server. Please check extended error for additi
onal details.
Attempting to delete record: _kerberos._tcp.dc in zone alpha.local
Error deleting record: _kerberos._tcp.dc
Error details: InputObject for resource record has an invalid value. Failed to remove the resource record on dc2.alpha.local server. Please check extended error for additi
onal details.

Raw Data (that the code is working against) Snippet:

HostName                  RecordType Type       Timestamp            TimeToLive      RecordData                                        
--------                  ---------- ----       ---------            ----------      ----------                                        
_gc._tcp.Site1._sites     SRV        33         3/16/2024 4:00:00 AM 00:10:00        [0][100][3268][DC1.ALPHA.local.]                  
_gc._tcp.Site1._sites     SRV        33         3/14/2024 9:00:00 AM 00:10:00        [0][100][3268][dc1.alpha.local.]                  
_kerberos._tcp.Site1._... SRV        33         3/16/2024 4:00:00 AM 00:10:00        [0][100][88][DC1.ALPHA.local.]                    
_kerberos._tcp.Site1._... SRV        33         3/14/2024 9:00:00 AM 00:10:00        [0][100][88][dc1.alpha.local.]                    
_ldap._tcp.Site1._sites   SRV        33         3/16/2024 4:00:00 AM 00:10:00        [0][100][389][DC1.ALPHA.local.]                   
_ldap._tcp.Site1._sites   SRV        33         3/14/2024 9:00:00 AM 00:10:00        [0][100][389][dc1.alpha.local.]                   
_gc._tcp.Site2._sites     SRV        33         3/14/2024 8:00:00 AM 00:10:00        [0][100][3268][dc2.alpha.local.]                  
_kerberos._tcp.Site2._... SRV        33         3/14/2024 8:00:00 AM 00:10:00        [0][100][88][dc2.alpha.local.]    

Solution

  • After many re-writes and additional testing, this code below does the job. Sometimes you will have to re-run the script once or twice to delete everything but after doing that any SRV records containing upper case characters will be gone. For whatever reason, I could not get the code to format properly, even using the code sample button inside the StackOverflow formatting controls. I apologize for that.

    1. Replace $zoneNames & $zoneNames with your appropriate values.

    2. $dnsServer MUST be a 2016 DC or higher or it won't delete anything

    3. Any DC below 2016 should no longer be FSMO role holders

      $zoneNames =@("msdcs.alpha.local", "alpha.local") $dnsServer = 'dc2.alpha.local'
      $deletedRecords = @() foreach ($zoneName in $zoneNames) # Get all SRV records from the specified zones {$AllSrvRecords = Get-DnsServerResourceRecord -ZoneName $zoneName -RRType SRV -ComputerName $dnsServer | Where-Object {$
      .RecordData.DomainName -cmatch '[A-Z]'} foreach ($record in $allSrvRecords) {try { Write-Host "Attempting to delete record: $($record.HostName) in zone $($ZoneName)" $record | Remove-DnsServerResourceRecord -ZoneName $zoneName -ComputerName $dnsServer -Force $deletedRecords += $record Write-Host "Deleted record: $($record.HostName) in zone $ZoneName" } catch {Write-Host "Error deleting record: $($record.HostName)" Write-Host "Error details: $" }}} $deletedRecords | ForEach-Object { $.HostName } Write-Host "Deleted records: $($deletedRecords.count)"