Skip to content

Commit e4562e6

Browse files
authored
New Resources: DnsRecordTxt and DnsRecordTxtScoped (#297)
1 parent d6e3c5b commit e4562e6

18 files changed

+2439
-0
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
55

66
## [Unreleased]
77

8+
### Added
9+
10+
- DnsServerDsc
11+
- Added new resource
12+
- _DnsRecordTxt_ - resource to manage DNS TXT records ([issue #150](https://github.com/dsccommunity/DnsServerDsc/issues/150)).
13+
- _DnsRecordTxtScoped_ - resource to manage DNS TXT records ([issue #296](https://github.com/dsccommunity/DnsServerDsc/issues/296)).
14+
815
### Fixed
916

1017
- DnsServerSetting
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<#
2+
.SYNOPSIS
3+
The DnsRecordTxt DSC resource manages TXT DNS records against a specific zone on a Domain Name System (DNS) server.
4+
5+
.DESCRIPTION
6+
The DnsRecordTxt DSC resource manages TXT DNS records against a specific zone on a Domain Name System (DNS) server.
7+
8+
.PARAMETER Name
9+
Specifies the name of a DNS server resource record object.
10+
11+
.PARAMETER DescriptiveText
12+
Specifies additional text to describe a resource record on a DNS server. It is limited to 254 characters per line.
13+
14+
.NOTES
15+
About long and muli-lined DNS TXT records.
16+
17+
Microsoft DNS Server generally supports creating long multi-line TXT DNS records.
18+
For example, using the DNS MMC snap-in (which directly utilizes the DNS API), you can create a record containing multiple lines.
19+
However, when saving such a record, all lines will be truncated to 140 characters.
20+
21+
Using the Add-DnsServerResourceRecord cmdlet (PowerShell/WMI), you can create a single-line record up to 254 characters long.
22+
However, it is not possible to create a multi-line DNS TXT record, thereby increasing the maximum possible record length beyond 254 characters.
23+
24+
There is also a method to create records using DNSCMD.EXE, but this approach does not support Scoped DNS TXT records.
25+
26+
For more details, refer to:
27+
https://learn.microsoft.com/en-us/answers/questions/1189058/how-to-set-multiline-txt-fields-with-add-dnsserver
28+
29+
Another Important Consideration:
30+
When attempting to retrieve the value of a multi-line TXT record using:
31+
```Powershell
32+
(Get-DnsServerResourceRecord -ZoneName $ZoneName -RRType TXT -Name $Name).RecordData.DescriptiveText
33+
```
34+
only the first line is returned.
35+
To obtain the full multi-line record, you would need to use:
36+
```Powershell
37+
Resolve-DnsName -Name $Name -Type TXT -Server $DnsServer
38+
```
39+
then you would parse Strings[] parameter of returned object like `Strings[0], Strings[1]... etc`.
40+
41+
Conclusion:
42+
Based on the above, this DSC resource only works with single-line DNS TXT records, limited to 254 characters maximum.
43+
44+
#>
45+
46+
[DscResource()]
47+
class DnsRecordTxt : DnsRecordBase
48+
{
49+
[DscProperty(Key)]
50+
[System.String]
51+
$Name
52+
53+
[DscProperty(Key)]
54+
[System.String]
55+
$DescriptiveText
56+
57+
DnsRecordTxt ()
58+
{
59+
}
60+
61+
[DnsRecordTxt] Get()
62+
{
63+
return ([DnsRecordBase] $this).Get()
64+
}
65+
66+
[void] Set()
67+
{
68+
([DnsRecordBase] $this).Set()
69+
}
70+
71+
[System.Boolean] Test()
72+
{
73+
return ([DnsRecordBase] $this).Test()
74+
}
75+
76+
hidden [Microsoft.Management.Infrastructure.CimInstance] GetResourceRecord()
77+
{
78+
Write-Verbose -Message ($this.localizedData.GettingDnsRecordMessage -f 'TXT', $this.ZoneName, $this.ZoneScope, $this.DnsServer)
79+
80+
$dnsParameters = @{
81+
ZoneName = $this.ZoneName
82+
ComputerName = $this.DnsServer
83+
RRType = 'TXT'
84+
Name = $this.Name
85+
}
86+
87+
if ($this.isScoped)
88+
{
89+
$dnsParameters['ZoneScope'] = $this.ZoneScope
90+
}
91+
92+
$record = Get-DnsServerResourceRecord @dnsParameters -ErrorAction SilentlyContinue | Where-Object -FilterScript {
93+
$_.RecordData.DescriptiveText -eq $this.DescriptiveText
94+
}
95+
96+
return $record
97+
}
98+
99+
hidden [DnsRecordTxt] NewDscResourceObjectFromRecord([Microsoft.Management.Infrastructure.CimInstance] $record)
100+
{
101+
$dscResourceObject = [DnsRecordTxt] @{
102+
ZoneName = $this.ZoneName
103+
Name = $this.Name
104+
DescriptiveText = $this.DescriptiveText
105+
TimeToLive = $record.TimeToLive.ToString()
106+
DnsServer = $this.DnsServer
107+
Ensure = 'Present'
108+
}
109+
110+
return $dscResourceObject
111+
}
112+
113+
hidden [void] AddResourceRecord()
114+
{
115+
$dnsParameters = @{
116+
ZoneName = $this.ZoneName
117+
ComputerName = $this.DnsServer
118+
TXT = $true
119+
Name = $this.Name
120+
DescriptiveText = $this.DescriptiveText
121+
}
122+
123+
if ($this.isScoped)
124+
{
125+
$dnsParameters['ZoneScope'] = $this.ZoneScope
126+
}
127+
128+
if ($null -ne $this.TimeToLive)
129+
{
130+
$dnsParameters.Add('TimeToLive', $this.TimeToLive)
131+
}
132+
133+
Write-Verbose -Message ($this.localizedData.CreatingDnsRecordMessage -f 'TXT', $this.ZoneName, $this.ZoneScope, $this.DnsServer)
134+
135+
Add-DnsServerResourceRecord @dnsParameters
136+
}
137+
138+
hidden [void] ModifyResourceRecord([Microsoft.Management.Infrastructure.CimInstance] $existingRecord, [System.Collections.Hashtable[]] $propertiesNotInDesiredState)
139+
{
140+
$dnsParameters = @{
141+
ZoneName = $this.ZoneName
142+
ComputerName = $this.DnsServer
143+
}
144+
145+
if ($this.isScoped)
146+
{
147+
$dnsParameters['ZoneScope'] = $this.ZoneScope
148+
}
149+
150+
# Copy the existing record and modify values as appropriate
151+
$newRecord = [Microsoft.Management.Infrastructure.CimInstance]::new($existingRecord)
152+
153+
foreach ($propertyToChange in $propertiesNotInDesiredState)
154+
{
155+
switch ($propertyToChange.Property)
156+
{
157+
# Key parameters will never be affected, so only include Mandatory and Optional values in the switch statement
158+
'TimeToLive'
159+
{
160+
$newRecord.TimeToLive = [System.TimeSpan] $propertyToChange.ExpectedValue
161+
}
162+
163+
}
164+
}
165+
166+
Set-DnsServerResourceRecord @dnsParameters -OldInputObject $existingRecord -NewInputObject $newRecord -Verbose
167+
}
168+
169+
# Called by ResourceBase class in Get() Set() and Test() methods to assert that all properties are valid.
170+
hidden [void] AssertProperties([System.Collections.Hashtable] $properties)
171+
{
172+
switch ($properties.keys)
173+
{
174+
'DescriptiveText'
175+
{
176+
if ($properties.DescriptiveText.Length -lt 1 -or $properties.DescriptiveText.Length -gt 254)
177+
{
178+
$errorMessage = $this.localizedData.PropertyIsNotInValidRange -f 'DescriptiveText'
179+
New-InvalidOperationException -Message $errorMessage
180+
}
181+
}
182+
}
183+
184+
}
185+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<#
2+
.SYNOPSIS
3+
The DnsRecordTxtScoped DSC resource manages TXT DNS records against a specific zone and zone scope on a Domain Name System (DNS) server.
4+
5+
.DESCRIPTION
6+
The DnsRecordTxtScoped DSC resource manages TXT DNS records against a specific zone and zone scope on a Domain Name System (DNS) server.
7+
8+
.PARAMETER ZoneScope
9+
Specifies the name of a zone scope. (Key Parameter)
10+
#>
11+
12+
[DscResource()]
13+
class DnsRecordTxtScoped : DnsRecordTxt
14+
{
15+
[DscProperty(Key)]
16+
[System.String]
17+
$ZoneScope
18+
19+
DnsRecordTxtScoped ()
20+
{
21+
}
22+
23+
[DnsRecordTxtScoped] Get()
24+
{
25+
return ([DnsRecordBase] $this).Get()
26+
}
27+
28+
[void] Set()
29+
{
30+
([DnsRecordBase] $this).Set()
31+
}
32+
33+
[System.Boolean] Test()
34+
{
35+
return ([DnsRecordBase] $this).Test()
36+
}
37+
38+
hidden [Microsoft.Management.Infrastructure.CimInstance] GetResourceRecord()
39+
{
40+
return ([DnsRecordTxt] $this).GetResourceRecord()
41+
}
42+
43+
hidden [DnsRecordTxtScoped] NewDscResourceObjectFromRecord([Microsoft.Management.Infrastructure.CimInstance] $record)
44+
{
45+
$dscResourceObject = [DnsRecordTxtScoped] @{
46+
ZoneName = $this.ZoneName
47+
ZoneScope = $this.ZoneScope
48+
Name = $this.Name
49+
DescriptiveText = $this.DescriptiveText
50+
TimeToLive = $record.TimeToLive.ToString()
51+
DnsServer = $this.DnsServer
52+
Ensure = 'Present'
53+
}
54+
55+
return $dscResourceObject
56+
}
57+
58+
hidden [void] AddResourceRecord()
59+
{
60+
([DnsRecordTxt] $this).AddResourceRecord()
61+
}
62+
63+
hidden [void] ModifyResourceRecord([Microsoft.Management.Infrastructure.CimInstance] $existingRecord, [System.Collections.Hashtable[]] $propertiesNotInDesiredState)
64+
{
65+
([DnsRecordTxt] $this).ModifyResourceRecord($existingRecord, $propertiesNotInDesiredState)
66+
}
67+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<#PSScriptInfo
2+
3+
.VERSION 1.0.1
4+
5+
.GUID e5aa793c-ecfc-4b7c-ac2b-a24847458b84
6+
7+
.AUTHOR DSC Community
8+
9+
.COMPANYNAME DSC Community
10+
11+
.COPYRIGHT DSC Community contributors. All rights reserved.
12+
13+
.TAGS DSCConfiguration
14+
15+
.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE
16+
17+
.PROJECTURI https://github.com/dsccommunity/DnsServerDsc
18+
19+
.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png
20+
21+
.EXTERNALMODULEDEPENDENCIES
22+
23+
.REQUIREDSCRIPTS
24+
25+
.EXTERNALSCRIPTDEPENDENCIES
26+
27+
.RELEASENOTES
28+
Updated author, copyright notice, and URLs.
29+
30+
.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core
31+
32+
#>
33+
34+
#Requires -Module DnsServerDsc
35+
36+
37+
<#
38+
.DESCRIPTION
39+
This configuration will ensure a DNS TXT record exists when only the mandatory properties are specified.
40+
#>
41+
42+
Configuration DnsRecordTxt_Mandatory_config
43+
{
44+
Import-DscResource -ModuleName 'DnsServerDsc'
45+
46+
Node localhost
47+
{
48+
DnsRecordTxt 'TestRecord'
49+
{
50+
ZoneName = 'contoso.com'
51+
Name = 'test'
52+
DescriptiveText = 'Example text for test.contoso.com TXT record.'
53+
Ensure = 'Present'
54+
}
55+
}
56+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<#PSScriptInfo
2+
3+
.VERSION 1.0.1
4+
5+
.GUID 69b26e36-d45d-4621-b5d2-5bfed0503c10
6+
7+
.AUTHOR DSC Community
8+
9+
.COMPANYNAME DSC Community
10+
11+
.COPYRIGHT DSC Community contributors. All rights reserved.
12+
13+
.TAGS DSCConfiguration
14+
15+
.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE
16+
17+
.PROJECTURI https://github.com/dsccommunity/DnsServerDsc
18+
19+
.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png
20+
21+
.EXTERNALMODULEDEPENDENCIES
22+
23+
.REQUIREDSCRIPTS
24+
25+
.EXTERNALSCRIPTDEPENDENCIES
26+
27+
.RELEASENOTES
28+
Updated author, copyright notice, and URLs.
29+
30+
.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core
31+
32+
#>
33+
34+
#Requires -Module DnsServerDsc
35+
36+
37+
<#
38+
.DESCRIPTION
39+
This configuration will ensure a DNS TXT record exists when all properties are specified.
40+
#>
41+
42+
Configuration DnsRecordTxt_Full_config
43+
{
44+
Import-DscResource -ModuleName 'DnsServerDsc'
45+
46+
Node localhost
47+
{
48+
DnsRecordTxt 'TestRecord Multiline Full'
49+
{
50+
ZoneName = 'contoso.com'
51+
Name = 'sea2048._domainkey'
52+
DescriptiveText = 'Example text for test.contoso.com TXT record.'
53+
TimeToLive = '01:00:00'
54+
DnsServer = 'localhost'
55+
Ensure = 'Present'
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)