POSHOrigin_ActiveDirectoryDNS.psm1
#Requires -Version 5.0 #Requires -Module DnsServer enum Ensure { Absent Present } [DscResource()] class ARecord { [DscProperty(key)] [string]$Name [DscProperty()] [Ensure]$Ensure = [ensure]::Present [DscProperty(Mandatory)] [string]$DnsServer [DscProperty(Mandatory)] [pscredential]$Credential [DscProperty(Mandatory)] [string]$IPAddress [DscProperty(Mandatory)] [string]$ZoneName [DscProperty()] [int]$TTL [DscProperty()] [bool]$CreatePtr = $true [DscProperty()] [bool]$AllowUpdateAny = $false [DscProperty()] [bool]$AgeRecord = $false [Microsoft.Management.Infrastructure.CimSession] Init() { try { Import-Module -Name DnsServer -Verbose:$false -Debug:$false $cim = New-CimSession -ComputerName $this.DnsServer -Credential $this.Credential -Verbose:$false return $cim } catch { throw "Unable to establish CIM session with $($this.DnsServer)" } } [ARecord]Get() { $result = [ARecord]::new() try { $cim = $this.Init() $result.Name = $this.Name $result.ZoneName = $this.ZoneName $result.DnsServer = $this.DnsServer $result.Credential = $this.Credential $result.AllowUpdateAny = $this.AllowUpdateAny $result.CreatePtr = $this.CreatePtr $params = @{ RRType = 'A' CimSession = $cim ZoneName = $this.ZoneName Name = $this.Name Verbose = $false } Write-Verbose -Message "Finding Record: $($this.Name) in zone $($this.ZoneName)" $record = Get-DnsServerResourceRecord @params -ErrorAction SilentlyContinue if ($record) { $result.Ensure = [Ensure]::Present $result.IPAddress = $record.RecordData.IPv4Address.ToString() $result.AgeRecord = ($record.TimeStamp -ne $null) $result.TTL = $record.TimeToLive.TotalSeconds } else { $result.Ensure = [Ensure]::Absent } $cim | Remove-CimSession } catch { Write-Error -Message 'There was a problem getting the resource' Write-Error -Message "$($_.InvocationInfo.ScriptName)($($_.InvocationInfo.ScriptLineNumber)): $($_.InvocationInfo.Line)" Write-Error -Exception $_ } return $result } [void]Set() { $cim = $null try { $cim = $this.Init() $record = $this.Get() switch ($this.Ensure) { 'Present' { # Does the record already exist? if ($record.Ensure -eq [ensure]::Present) { # Get a copy of the DNS record $params = @{ RRType = 'A' CimSession = $cim ZoneName = $this.ZoneName Name = $this.Name Verbose = $false } $oldRecord = Get-DnsServerResourceRecord @params $newRecord = Get-DnsServerResourceRecord @params #region Resource exists but lets test if we need to change anything on it $changed = $false # Set IP Address if ($oldRecord.RecordData.IPv4Address.ToString() -ne $this.IPAddress) { $newRecord.RecordData.IPv4Address = [ipaddress]::Parse($this.IPAddress) $updateParams = @{ NewInputObject = $newRecord OldInputObject = $oldRecord ZoneName = $this.ZoneName CimSession = $cim Confirm = $true } Write-Verbose -Message "Changing record: $($this.Name) to IP address -> $($this.IPAddress) in zone $($this.ZoneName)" Set-DnsServerResourceRecord @params } # Set CreatePtr # TODO # Set AgeRecord # TODO # SetAllowUpdateAny # TODO #endregion if (-Not $changed) { Write-Verbose -Message 'No changes needed' } } else { # Create record $params = @{ Name = $this.Name ZoneName = $this.ZoneName CreatePtr = $this.CreatePtr IPv4Address = $this.IPAddress TimeToLive = [System.TimeSpan]::FromSeconds($this.TTL) AgeRecord = $this.AgeRecord AllowUpdateAny = $this.AllowUpdateAny CimSession = $cim Verbose = $false } Write-Verbose -Message "Creating record: $($this.Name) -> $($this.IPAddress) in zone $($this.ZoneName)" Add-DnsServerResourceRecordA @params } } 'Absent' { if ($record.Ensure = [ensure]::Present) { # Delete record $params = @{ Name = $this.Name ZoneName = $this.ZoneName RRType = 'A' CimSession = $cim Force = $true Verbose = $false } Write-Verbose -Message "Removing record: $($this.Name) ($($this.IPAddress)) from zone $($this.ZoneName)" Remove-DnsServerResourceRecord @params } else { # Do nothing } } } } catch { Write-Error -Message 'There was a problem setting the resource' Write-Error -Message "$($_.InvocationInfo.ScriptName)($($_.InvocationInfo.ScriptLineNumber)): $($_.InvocationInfo.Line)" Write-Error -Exception $_ $cim | Remove-CimSession } } [bool]Test() { $record = $this.Get() Write-Verbose -Message "Validating that record $($this.Name) in $($this.ZoneName) is $($this.Ensure.ToString().ToLower())" if ($this.Ensure -ne $record.Ensure) { return $false } elseif ($this.Ensure -eq [ensure]::Present -and ($record.IPAddress -ne $this.IPAddress)) { return $false } return $true } } [DscResource()] class CName { [DscProperty(key)] [string]$Name [DscProperty()] [Ensure]$Ensure = [ensure]::Present [DscProperty(Mandatory)] [string]$DnsServer [DscProperty(Mandatory)] [pscredential]$Credential [DscProperty(Mandatory)] [string]$ZoneName [DscProperty(Mandatory)] [string]$FQDN [DscProperty()] [int]$TTL [DscProperty()] [bool]$AllowUpdateAny = $false [DscProperty()] [bool]$AgeRecord = $false [Microsoft.Management.Infrastructure.CimSession] Init() { try { Import-Module -Name DnsServer -Verbose:$false -Debug:$false $cim = New-CimSession -ComputerName $this.DnsServer -Credential $this.Credential -Verbose:$false return $cim } catch { throw "Unable to establish CIM session with $($this.DnsServer)" } } [CName]Get() { $result = [Cname]::new() try { $record = $null $cim = $this.Init() $result.Name = $this.Name $result.ZoneName = $this.ZoneName $result.DnsServer = $this.DnsServer $result.Credential = $this.Credential $result.AllowUpdateAny = $this.AllowUpdateAny $params = @{ RRType = 'CNAME' CimSession = $cim ZoneName = $this.ZoneName Name = $this.Name Verbose = $false } Write-Verbose -Message "Finding record: $($this.Name) in zone $($this.ZoneName)" $record = Get-DnsServerResourceRecord @params -ErrorAction SilentlyContinue if ($record) { $result.Ensure = [Ensure]::Present $result.FQDN = $record.RecordData.HostNameAlias.TrimEnd('.') $result.AgeRecord = ($record.TimeStamp -ne $null) $result.TTL = $record.TimeToLive.TotalSeconds } else { $result.Ensure = [Ensure]::Absent } $cim | Remove-CimSession } catch { Write-Error -Message 'There was a problem getting the resource' Write-Error -Message "$($_.InvocationInfo.ScriptName)($($_.InvocationInfo.ScriptLineNumber)): $($_.InvocationInfo.Line)" Write-Error -Exception $_ } return $result } [void]Set() { $cim = $null try { $cim = $this.Init() $record = $this.Get() switch ($this.Ensure) { 'Present' { # Does the record already exist? if ($record.Ensure -eq [ensure]::Present) { # Get a copy of the DNS record $params = @{ RRType = 'CName' CimSession = $cim ZoneName = $this.ZoneName Name = $this.Name Verbose = $false } $oldRecord = Get-DnsServerResourceRecord @params $newRecord = Get-DnsServerResourceRecord @params #region Resource exists but lets test if we need to change anything on it $changed = $false # Set IP Address $oldHostNameAlias= $oldRecord.RecordData.HostNameAlias.TrimEnd('.') if ($oldHostNameAlias -ne $this.FQDN) { $newRecord.RecordData.HostNameAlias = $this.FQDN $updateParams = @{ NewInputObject = $newRecord OldInputObject = $oldRecord ZoneName = $this.ZoneName CimSession = $cim Confirm = $true } Write-Verbose -Message "Changing record: $($this.Name) FQDN -> $($this.FQDN)" Set-DnsServerResourceRecord @params } # Set AgeRecord # TODO # SetAllowUpdateAny # TODO #endregion if (-Not $changed) { Write-Verbose -Message 'No changes needed' } } else { # Create record $params = @{ Name = $this.Name ZoneName = $this.ZoneName HostNameAlias = $this.FQDN TimeToLive = [System.TimeSpan]::FromSeconds($this.TTL) AgeRecord = $this.AgeRecord AllowUpdateAny = $this.AllowUpdateAny CimSession = $cim Verbose = $false } Write-Verbose -Message "Creating record: $($this.Name) -> $($this.FQDN) in zone $($this.ZoneName)" Add-DnsServerResourceRecordCName @params } } 'Absent' { if ($record.Ensure = [ensure]::Present) { # Delete record $params = @{ Name = $this.Name ZoneName = $this.ZoneName RRType = 'CName' CimSession = $cim Force = $true Verbose = $false } Write-Verbose -Message "Removing record: $($this.Name) ($($this.FQDN)) from zone $($this.ZoneName)" Remove-DnsServerResourceRecord @params } else { # Do nothing } } } } catch { Write-Error -Message 'There was a problem setting the resource' Write-Error -Message "$($_.InvocationInfo.ScriptName)($($_.InvocationInfo.ScriptLineNumber)): $($_.InvocationInfo.Line)" Write-Error -Exception $_ $cim | Remove-CimSession } } [bool]Test() { $record = $this.Get() Write-Verbose -Message "Validating that record $($this.Name) in $($this.ZoneName) is $($this.Ensure.ToString().ToLower())" if ($this.Ensure -ne $record.Ensure) { Write-Verbose -Message "Record is [$($record.Ensure)]" return $false } elseif ($this.Ensure -eq [ensure]::Present -and ($record.FQDN -ne $this.FQDN)) { Write-Verbose -Message "FQDN $($record.FQDN) <> $($this.FQDN)" return $false } return $true } } |