-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DnsRecordPtr: Re-implemented as a class-based resource with IPv6 supp…
…ort. (#213) - DnsRecordPtr - Added new resource to manage PTR records
- Loading branch information
Showing
17 changed files
with
2,156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
<# | ||
.SYNOPSIS | ||
The DnsRecordPtr DSC resource manages PTR DNS records against a specific zone on a Domain Name System (DNS) server. | ||
.DESCRIPTION | ||
The DnsRecordPtr DSC resource manages PTR DNS records against a specific zone on a Domain Name System (DNS) server. | ||
.PARAMETER IpAddress | ||
Specifies the IP address to which the record is associated (Can be either IPv4 or IPv6. (Key Parameter) | ||
.PARAMETER Name | ||
Specifies the FQDN of the host when you add a PTR resource record. (Key Parameter) | ||
.NOTES | ||
Reverse lookup zones do not support scopes, so there should be no DnsRecordPtrScoped subclass created. | ||
#> | ||
|
||
[DscResource()] | ||
class DnsRecordPtr : DnsRecordBase | ||
{ | ||
[DscProperty(Key)] | ||
[System.String] | ||
$IpAddress | ||
|
||
[DscProperty(Key)] | ||
[System.String] | ||
$Name | ||
|
||
hidden [System.String] $recordHostName | ||
|
||
[DnsRecordPtr] Get() | ||
{ | ||
# Ensure $recordHostName is set | ||
$this.recordHostName = $this.getRecordHostName($this.IpAddress) | ||
|
||
return ([DnsRecordBase] $this).Get() | ||
} | ||
|
||
[void] Set() | ||
{ | ||
# Ensure $recordHostName is set | ||
$this.recordHostName = $this.getRecordHostName($this.IpAddress) | ||
|
||
([DnsRecordBase] $this).Set() | ||
} | ||
|
||
[System.Boolean] Test() | ||
{ | ||
# Ensure $recordHostName is set | ||
$this.recordHostName = $this.getRecordHostName($this.IpAddress) | ||
|
||
return ([DnsRecordBase] $this).Test() | ||
} | ||
|
||
hidden [Microsoft.Management.Infrastructure.CimInstance] GetResourceRecord() | ||
{ | ||
Write-Verbose -Message ($this.localizedData.GettingDnsRecordMessage -f 'Ptr', $this.ZoneName, $this.ZoneScope, $this.DnsServer) | ||
|
||
$dnsParameters = @{ | ||
ZoneName = $this.ZoneName | ||
ComputerName = $this.DnsServer | ||
RRType = 'PTR' | ||
Name = $this.recordHostName | ||
} | ||
|
||
$record = Get-DnsServerResourceRecord @dnsParameters -ErrorAction SilentlyContinue | Where-Object -FilterScript { | ||
$_.RecordData.PtrDomainName -eq "$($this.Name)." | ||
} | ||
|
||
return $record | ||
} | ||
|
||
hidden [DnsRecordPtr] NewDscResourceObjectFromRecord([Microsoft.Management.Infrastructure.CimInstance] $record) | ||
{ | ||
$dscResourceObject = [DnsRecordPtr] @{ | ||
ZoneName = $this.ZoneName | ||
IpAddress = $this.IpAddress | ||
Name = $this.Name | ||
TimeToLive = $record.TimeToLive.ToString() | ||
DnsServer = $this.DnsServer | ||
Ensure = 'Present' | ||
} | ||
|
||
return $dscResourceObject | ||
} | ||
|
||
hidden [void] AddResourceRecord() | ||
{ | ||
$dnsParameters = @{ | ||
ZoneName = $this.ZoneName | ||
ComputerName = $this.DnsServer | ||
PTR = $true | ||
Name = $this.recordHostName | ||
PtrDomainName = $this.Name | ||
} | ||
|
||
if ($null -ne $this.TimeToLive) | ||
{ | ||
$dnsParameters.Add('TimeToLive', $this.TimeToLive) | ||
} | ||
|
||
Write-Verbose -Message ($this.localizedData.CreatingDnsRecordMessage -f 'PTR', $this.ZoneName, $this.ZoneScope, $this.DnsServer) | ||
|
||
Add-DnsServerResourceRecord @dnsParameters | ||
} | ||
|
||
hidden [void] ModifyResourceRecord([Microsoft.Management.Infrastructure.CimInstance] $existingRecord, [System.Collections.Hashtable[]] $propertiesNotInDesiredState) | ||
{ | ||
$dnsParameters = @{ | ||
ZoneName = $this.ZoneName | ||
ComputerName = $this.DnsServer | ||
} | ||
|
||
# Copy the existing record and modify values as appropriate | ||
$newRecord = [Microsoft.Management.Infrastructure.CimInstance]::new($existingRecord) | ||
|
||
foreach ($propertyToChange in $propertiesNotInDesiredState) | ||
{ | ||
switch ($propertyToChange.Property) | ||
{ | ||
# Key parameters will never be affected, so only include Mandatory and Optional values in the switch statement | ||
'TimeToLive' | ||
{ | ||
$newRecord.TimeToLive = [System.TimeSpan] $propertyToChange.ExpectedValue | ||
} | ||
|
||
} | ||
} | ||
|
||
Set-DnsServerResourceRecord @dnsParameters -OldInputObject $existingRecord -NewInputObject $newRecord -Verbose | ||
} | ||
|
||
# Take a compressed IPv6 string (i.e.: fd00::1) and expand it out to the full notation (i.e.: fd00:0000:0000:0000:0000:0000:0000:0001) | ||
hidden [System.String] expandIPv6String($string) | ||
{ | ||
# Split the string on the colons | ||
$segments = [System.Collections.ArrayList]::new(($string -split ':')) | ||
|
||
# Determine how many segments need to be added to reach the 8 required | ||
$blankSegmentCount = 8 - $segments.count | ||
|
||
# Insert missing segments | ||
for ($i = 0; $i -lt $blankSegmentCount; $i++) | ||
{ | ||
$segments.Insert(1, '0000') | ||
} | ||
|
||
# Pad out all segments with leading zeros | ||
$paddedSegments = $segments | ForEach-Object { | ||
$_.PadLeft(4, '0') | ||
} | ||
return ($paddedSegments -join ':') | ||
} | ||
|
||
# Translate the IP address to the reverse notation used by the DNS server | ||
hidden [System.String] getReverseNotation([System.Net.IpAddress] $ipAddressObj) | ||
{ | ||
$significantData = [System.Collections.ArrayList]::New() | ||
|
||
switch ($ipAddressObj.AddressFamily) | ||
{ | ||
'InterNetwork' | ||
{ | ||
$significantData.AddRange(($ipAddressObj.IPAddressToString -split '\.')) | ||
break | ||
} | ||
|
||
'InterNetworkV6' | ||
{ | ||
# Get the hex values into an ArrayList | ||
$significantData.AddRange(($this.expandIPv6String($ipAddressObj.IPAddressToString) -replace ':', '' -split '')) | ||
break | ||
} | ||
} | ||
|
||
$significantData.Reverse() | ||
|
||
# The reverse lookup notation puts a '.' between each hex value | ||
return ($significantData -join '.').Trim('.') | ||
} | ||
|
||
# Determine the record host name | ||
hidden [System.String] getRecordHostName([System.Net.IpAddress] $ipAddressObj) | ||
{ | ||
$reverseLookupAddressComponent = "" | ||
|
||
switch ($ipAddressObj.AddressFamily) | ||
{ | ||
'InterNetwork' | ||
{ | ||
if (-not $this.ZoneName.ToLower().EndsWith('.in-addr.arpa')) | ||
{ | ||
throw ($this.localizedData.NotAnIPv4Zone -f $this.ZoneName) | ||
} | ||
$reverseLookupAddressComponent = $this.ZoneName.Replace('.in-addr.arpa', '') | ||
break | ||
} | ||
|
||
'InterNetworkV6' | ||
{ | ||
if (-not $this.ZoneName.ToLower().EndsWith('.ip6.arpa')) | ||
{ | ||
throw ($this.localizedData.NotAnIPv6Zone -f $this.ZoneName) | ||
} | ||
$reverseLookupAddressComponent = $this.ZoneName.Replace('.ip6.arpa', '') | ||
break | ||
} | ||
} | ||
|
||
$reverseNotation = $this.getReverseNotation($ipAddressObj) | ||
|
||
# Check to make sure that the ip address actually belongs in this zone | ||
if ($reverseNotation -notmatch "$($reverseLookupAddressComponent)`$") | ||
{ | ||
throw $this.localizedData.WrongZone -f $ipAddressObj.IPAddressToString, $this.ZoneName | ||
} | ||
|
||
# Strip the zone name from the reversed IP using a regular expression | ||
$ptrRecordHostName = $reverseNotation -replace "\.$([System.Text.RegularExpressions.Regex]::Escape($reverseLookupAddressComponent))`$", "" | ||
|
||
return $ptrRecordHostName | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
source/Examples/Resources/DnsRecordPtr/1-DnsRecordPtr_Mandatory_config.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<#PSScriptInfo | ||
.VERSION 1.0.1 | ||
.GUID 1133365f-c781-4f18-9cb5-96ca1c282c87 | ||
.AUTHOR DSC Community | ||
.COMPANYNAME DSC Community | ||
.COPYRIGHT DSC Community contributors. All rights reserved. | ||
.TAGS DSCConfiguration | ||
.LICENSEURI https://github.com/dsccommunity/xDnsServer/blob/main/LICENSE | ||
.PROJECTURI https://github.com/dsccommunity/xDnsServer | ||
.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png | ||
.EXTERNALMODULEDEPENDENCIES | ||
.REQUIREDSCRIPTS | ||
.EXTERNALSCRIPTDEPENDENCIES | ||
.RELEASENOTES | ||
Updated author, copyright notice, and URLs. | ||
.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core | ||
#> | ||
|
||
#Requires -Module xDnsServer | ||
|
||
|
||
<# | ||
.DESCRIPTION | ||
This configuration will ensure a DNS PTR record exists when only the mandatory properties are specified. | ||
#> | ||
|
||
Configuration DnsRecordPtr_Mandatory_config | ||
{ | ||
Import-DscResource -ModuleName 'xDnsServer' | ||
|
||
Node localhost | ||
{ | ||
DnsRecordPtr 'TestRecord' | ||
{ | ||
ZoneName = '0.168.192.in-addr.arpa' | ||
IpAddress = '192.168.0.9' | ||
Name = 'quarks.contoso.com' | ||
Ensure = 'Present' | ||
} | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
source/Examples/Resources/DnsRecordPtr/2-DnsRecordPtr_Full_config.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<#PSScriptInfo | ||
.VERSION 1.0.1 | ||
.GUID 5aa5cffa-4e3a-4861-b601-73f234015bc9 | ||
.AUTHOR DSC Community | ||
.COMPANYNAME DSC Community | ||
.COPYRIGHT DSC Community contributors. All rights reserved. | ||
.TAGS DSCConfiguration | ||
.LICENSEURI https://github.com/dsccommunity/xDnsServer/blob/main/LICENSE | ||
.PROJECTURI https://github.com/dsccommunity/xDnsServer | ||
.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png | ||
.EXTERNALMODULEDEPENDENCIES | ||
.REQUIREDSCRIPTS | ||
.EXTERNALSCRIPTDEPENDENCIES | ||
.RELEASENOTES | ||
Updated author, copyright notice, and URLs. | ||
.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core | ||
#> | ||
|
||
#Requires -Module xDnsServer | ||
|
||
|
||
<# | ||
.DESCRIPTION | ||
This configuration will ensure a DNS PTR record exists when all properties are specified. | ||
#> | ||
|
||
Configuration DnsRecordPtr_Full_config | ||
{ | ||
Import-DscResource -ModuleName 'xDnsServer' | ||
|
||
Node localhost | ||
{ | ||
DnsRecordPtr 'TestRecord' | ||
{ | ||
ZoneName = '0.168.192.in-addr.arpa' | ||
IpAddress = '192.168.0.9' | ||
Name = 'quarks.contoso.com' | ||
TimeToLive = '01:00:00' | ||
DnsServer = 'localhost' | ||
Ensure = 'Present' | ||
} | ||
} | ||
} |
Oops, something went wrong.