Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,8 @@
"pester.runTestsInNewProcess": true,
"pester.pesterModulePath": "./output/RequiredModules/Pester",
"powershell.pester.codeLens": true,
"pester.suppressCodeLensNotice": true
"pester.suppressCodeLensNotice": true,
"githubPullRequests.ignoredPullRequestBranches": [
"main"
]
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- DnsServerDsc.Common
- Removed `Test-DnsDscParameterState` and associated localization entries.

### Added

- DnsServerDsc
- Added new resource
-DSC_DnsServerStubZone - Added a new resource to manage file-backed DNS Stub Zones since it didn't previously exist and has been requested - https://github.com/dsccommunity/DnsServerDsc/issues/30
-Added on 4/10/2025

## [3.0.0] - 2021-05-26

### Removed
Expand Down
243 changes: 243 additions & 0 deletions source/DSCResources/DSC_DNSServerStubZone/DSC_DnsServerStubZone.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
$script:dscResourceCommonPath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\DscResource.Common'
$script:dnsServerDscCommonPath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\DnsServerDsc.Common'

Import-Module -Name $script:dscResourceCommonPath
Import-Module -Name $script:dnsServerDscCommonPath

$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US'

function Get-TargetResource
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$Name,

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$MasterServers,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ZoneFile = "$Name.dns",

[Parameter()]
[ValidateSet('Present','Absent')]
[System.String]
$Ensure = 'Present'
)

Assert-Module -ModuleName 'DNSServer'

Write-Verbose ($script:localizedData.CheckingZoneMessage -f $Name, $Ensure)

$dnsServerZone = Get-DnsServerZone -Name $Name -ErrorAction SilentlyContinue

$targetResource = @{
Name = $Name
MasterServers = $dnsServerZone.MasterServers | ForEach-Object { $_.IPAddressToString }
ZoneFile = $dnsServerZone.ZoneFile
Ensure = if (-not $dnsServerZone) { 'Absent' } else { 'Present' }
}

return $targetResource

} #end function Get-TargetResource

function Test-TargetResource
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At no point do you test the current zone type which is going to make for some exciting results if the zone exists as primary or secondary.

I would consider it legitimate for this resource to bail out with an error if the zone exists but is of the wrong type. However, you may also consider it correct to fix the problem. I'd defer to other folks on common handling though @johlju and @dan-hughes.

Whatever happens, you should check zone type and handle it appropriately. Blinding assuming that it can only possibly be a stub zone is a recipe for disaster.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed, but always welcome a second set of eyes.

{
[CmdletBinding()]
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$Name,

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$MasterServers,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ZoneFile = "$Name.dns",

[Parameter()]
[ValidateSet('Present','Absent')]
[System.String]
$Ensure = 'Present'
)

$targetResource = Get-TargetResource @PSBoundParameters
$targetResourceInCompliance = $true
$dnsServerZone = Get-DnsServerZone -Name $Name -ErrorAction SilentlyContinue

#If we specify that we want to ensure the zone should be ABSENT, check compliance.
if ($Ensure -eq 'Absent')
{
#If the results of our Get-TargetResource shows that the zone is PRESENT, set compliance, because we want it to be absent.
if ($targetResource.Ensure -eq 'Present')
{
# Dns zone is present and should be absent. '{0}' '{1}' '{2}' <--- Definitions in the DSC_DnsServerStubZone.strings.psd1
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'Ensure', 'Absent', 'Present')

$targetResourceInCompliance = $false
return $targetResourceInCompliance

}
}
#If we specify that we want to ensure the zone should be PRESENT, check compliance.
if ($Ensure -eq 'Present')
{
#If the results of our Get-TargetResource shows that the zone is PRESENT, set compliance, because we want it to be absent.
if ($targetResource.Ensure -eq 'Absent')
{
# Dns zone is absent and should be present.
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'Ensure', 'Present', 'Absent')

$targetResourceInCompliance = $false
return $targetResourceInCompliance
}

#If the results of our Get-TargetResource shows that the zone is PRESENT, move on to the next validation check.
if ($targetResource.Ensure -eq 'Present')
{
#If the Zone is AD integrated, set non-compliance.
if ($dnsServerZone.IsDSIntegrated -eq $true)
{
#Zone Storage differs from the desired configuration
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'ZoneStorageLocation', 'Active Directory', 'File')

$targetResourceInCompliance = $false
return $targetResourceInCompliance
}
#If the ZoneType isn't of type Stub, set non-compliance.
if ($dnsServerZone.ZoneType -ne 'Stub')
{
#Zone Type differs from the desired configuration
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'ZoneType', 'Stub', $dnsServerZone.ZoneType)

$targetResourceInCompliance = $false
return $targetResourceInCompliance
}
#If the Zone File name differ from the desired configuration, set non-compliance.
if ($targetResource.ZoneFile -ne $ZoneFile)
Copy link
Contributor

@indented-automation indented-automation Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens to this value if the stub zone is DS integrated?

This effectively an extension of checking the zone type. You blindly assume that the zone either does not exist or is already a (file based) stub zone.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed, but always welcome a second set of eyes.

{
#ZoneFile name differs from the desired configuration
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'ZoneFile', $targetResource.ZoneFile, $ZoneFile)

$targetResourceInCompliance = $false
return $targetResourceInCompliance
}
#If the Master Servers differ from the desired configuration, set non-compliance.
$Comparison = Compare-Object -ReferenceObject $MasterServers -DifferenceObject $targetResource.MasterServers
if ($Comparison)
{
#Zone Master Servers differ from the desired configuration
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'MasterServers', ($MasterServers -join ','), ($targetResource.MasterServers -join ','))
$targetResourceInCompliance = $false
}

return $targetResourceInCompliance

}

}

} #end function Test-TargetResource

function Set-TargetResource
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$Name,

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$MasterServers,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ZoneFile = "$Name.dns",

[Parameter()]
[ValidateSet('Present','Absent')]
[System.String]
$Ensure = 'Present'
)

Assert-Module -ModuleName 'DNSServer'
$targetResource = Get-TargetResource @PSBoundParameters
$dnsServerZone = Get-DnsServerZone -Name $Name -ErrorAction SilentlyContinue

if ($Ensure -eq 'Absent')
{
Write-Verbose ($script:localizedData.CheckingZoneMessage -f $Name, $Ensure)

if ($dnsServerZone.type -eq 'Stub' -and $dnsServerZone.IsDSIntegrated -eq $false)
{

# Remove the DNS Server zone.
Write-Verbose ($script:localizedData.RemovingZoneMessage -f $Name)
Get-DnsServerZone -Name $Name | Remove-DnsServerZone -Force

}
else
{
if ($dnsServerZone.type -ne 'Stub')
{

# Zone is not a stub zone.
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'ZoneType', 'Stub', $dnsServerZone.ZoneType)
}
if ($dnsServerZone.IsDSIntegrated -ne $false)
{

# Zone is AD integrated.
Write-Verbose ($script:localizedData.NotDesiredPropertyMessage -f 'ZoneStorageLocation', 'Active Directory', 'File')
}

}
}

if ($Ensure -eq 'Present')
{
Write-Verbose ($script:localizedData.CheckingZoneMessage -f $Name, $Ensure)

if ($dnsServerZone.ZoneType -eq 'Stub' -and $dnsServerZone.IsDSIntegrated -eq $false)
{
# Compare the Desired master servers to the Existing master servers - if Existing doesn't match Desired, update the master servers for the zone.
$Comparison = Compare-Object -ReferenceObject $MasterServers -DifferenceObject $targetResource.MasterServers

#If the Master Servers differ from the desired configuration, set them to the desired configuration.
if ($Comparison)
{
# Update the Master Servers list
Set-DnsServerStubZone -Name $Name -MasterServers $MasterServers

Write-Verbose ($script:localizedData.SetPropertyMessage -f 'MasterServers')
}

}
elseif (-not $dnsServerZone)
{
# Create the DNS Server zone.
Add-DnsServerStubZone -Name $Name -ZoneFile $ZoneFile -MasterServers $MasterServers

Write-Verbose ($script:localizedData.AddingZoneMessage -f $Name)
}
}

} #end function Set-TargetResource
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[ClassVersion("1.0.0.0"), FriendlyName("DnsServerStubZone")]
class DSC_DnsServerStubZone : OMI_BaseResource
{
[Key, Description("Name of the DNS Server stub zone")] String Name;
[Write, Description("Name of the DNS Server stub zone file. If not specified, defaults to 'ZoneName.dns'.")] String ZoneFile;
[Required, Description("List of master server IP addresses used by the stub zone.")] String MasterServers[];
[Write, Description("Whether the DNS zone should be present or absent"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
};
3 changes: 3 additions & 0 deletions source/DSCResources/DSC_DNSServerStubZone/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Description

The DnsServerStubZone DSC resource manages a standalone file-backed Stub zone on a given Domain Name System (DNS) server.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# culture="en-US"
ConvertFrom-StringData @'
CheckingZoneMessage = Checking DNS server zone with name '{0}' is '{1}'...
AddingZoneMessage = Adding DNS server zone '{0}' ...
RemovingZoneMessage = Removing DNS server zone '{0}' ...
NotDesiredPropertyMessage = DNS server zone property '{0}' is not correct. Expected '{1}', Actual '{2}'
SetPropertyMessage = DNS server zone property '{0}' is set
'@
Loading
Loading