Last active
December 5, 2024 18:23
-
-
Save JohanSelmosson/5211c59aed035858b149b34cae78974c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
function Set-DhcpScopeSettings { | |
<# | |
.SYNOPSIS | |
Modifies DHCP scope settings including lease duration, DNS settings, and DNS domain for specified scopes. | |
.DESCRIPTION | |
This function allows bulk modification of DHCP scope settings on a specified DHCP server. | |
It can modify: | |
- Lease duration | |
- DNS servers | |
- DNS domain | |
- DNS dynamic update settings | |
- PTR record handling | |
- DNS record cleanup settings | |
All changes are tracked and returned as PowerShell objects for further processing or logging. | |
.PARAMETER DhcpServer | |
The name of the DHCP server to modify. Defaults to local computer. | |
.PARAMETER ScopeId | |
One or more scope IDs to modify. If not specified, all scopes will be processed. | |
.PARAMETER ExcludeScopeId | |
One or more scope IDs to exclude from processing. | |
.PARAMETER LeaseDurationMinutes | |
The new lease duration in minutes. Valid range: 1-999999. | |
.PARAMETER DnsServers | |
An array of DNS server IP addresses to set for the scopes. | |
.PARAMETER ClearDnsSettings | |
Switch to clear all DNS server settings from the scopes. | |
.PARAMETER DnsDomain | |
The DNS domain name to set for the scopes. | |
.PARAMETER ClearDnsDomain | |
Switch to clear the DNS domain setting from the scopes. | |
.PARAMETER SkipDnsValidation | |
Switch to skip DNS server validation when setting Option 6. | |
.PARAMETER DnsUpdateSetting | |
Specifies how DNS records are updated. Valid values: 'Never', 'OnClientRequest', 'Always'. | |
.PARAMETER RegisterPtrRecords | |
Switch to enable or disable PTR record registration for DHCP clients. | |
.PARAMETER DiscardRecordsOnExpiry | |
Switch to enable or disable DNS record cleanup when leases expire. | |
.PARAMETER OverrideClientRequest | |
Switch to enable or disable overriding client DNS update requests. | |
.PARAMETER Force | |
Switch to bypass the confirmation prompt before making changes. | |
.EXAMPLE | |
Set-DhcpScopeSettings -DhcpServer "dhcp01" -LeaseDurationMinutes 1440 | |
Sets lease duration to 24 hours for all scopes on dhcp01. | |
.EXAMPLE | |
Set-DhcpScopeSettings -ScopeId "192.168.1.0" -DnsServers "10.0.0.1","10.0.0.2" -Force | |
Updates DNS servers for a specific scope without confirmation prompt. | |
.EXAMPLE | |
Set-DhcpScopeSettings -ExcludeScopeId "10.0.0.0" -RegisterPtrRecords:$false | |
Disables PTR record registration for all scopes except 10.0.0.0. | |
.EXAMPLE | |
Set-DhcpScopeSettings -DnsUpdateSetting OnClientRequest -DiscardRecordsOnExpiry | |
Sets DNS update behavior to client-initiated and enables record cleanup on lease expiry. | |
.NOTES | |
Author: Johan Selmosson | |
Version: 2.0 | |
Updated: 2024-12-05 | |
Requirements: | |
- Windows DHCP Server PowerShell module | |
- Administrative privileges on the DHCP server | |
#> | |
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] | |
param ( | |
[Parameter(Mandatory = $false, Position = 0)] | |
[string]$DhcpServer = $env:COMPUTERNAME, | |
[Parameter(Mandatory = $false, Position = 1)] | |
[string[]]$ScopeId, | |
[Parameter(Mandatory = $false)] | |
[string[]]$ExcludeScopeId, | |
[Parameter(Mandatory = $false, Position = 2)] | |
[ValidateRange(1, 999999)] | |
[int]$LeaseDurationMinutes, | |
[Parameter(Mandatory = $false)] | |
[string[]]$DnsServers, | |
[Parameter(Mandatory = $false)] | |
[switch]$ClearDnsSettings, | |
[Parameter(Mandatory = $false)] | |
[string]$DnsDomain, | |
[Parameter(Mandatory = $false)] | |
[switch]$ClearDnsDomain, | |
[Parameter(Mandatory = $false)] | |
[switch]$SkipDnsValidation, | |
[Parameter(Mandatory = $false)] | |
[ValidateSet('Never', 'OnClientRequest', 'Always')] | |
[string]$DnsUpdateSetting, | |
[Parameter(Mandatory = $false)] | |
[switch]$RegisterPtrRecords, | |
[Parameter(Mandatory = $false)] | |
[switch]$DiscardRecordsOnExpiry, | |
[Parameter(Mandatory = $false)] | |
[switch]$OverrideClientRequest, | |
[Parameter(Mandatory = $false)] | |
[switch]$Force | |
) | |
begin { | |
$script:plannedChanges = @() | |
$script:changes = @() | |
} | |
process { | |
try { | |
Write-Host "`nStarting DHCP configuration update on server: " -NoNewline | |
Write-Host $DhcpServer -ForegroundColor Cyan | |
# Get scopes based on parameter | |
$scopes = if ($ScopeId) { | |
$ScopeId | ForEach-Object { | |
Get-DhcpServerv4Scope -ComputerName $DhcpServer -ScopeId $_ -ErrorAction Stop | |
} | |
} | |
else { | |
Get-DhcpServerv4Scope -ComputerName $DhcpServer | |
} | |
# Exclude specified scopes | |
if ($ExcludeScopeId) { | |
$scopes = $scopes | Where-Object { $ExcludeScopeId -notcontains $_.ScopeId } | |
} | |
Write-Host "`nFound" -NoNewline | |
Write-Host " $($scopes.Count) " -ForegroundColor Yellow -NoNewline | |
Write-Host "scopes to process`n" | |
foreach ($scope in $scopes) { | |
# Get current settings | |
$currentScope = Get-DhcpServerv4Scope -ComputerName $DhcpServer -ScopeId $scope.ScopeId | |
$currentLeaseMinutes = $currentScope.LeaseDuration.TotalMinutes | |
$currentDnsServers = (Get-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 6 -ErrorAction SilentlyContinue).Value | |
$currentDnsDomain = (Get-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 15 -ErrorAction SilentlyContinue).Value -join ", " | |
$currentDnsSettings = Get-DhcpServerv4DnsSetting -ComputerName $DhcpServer -ScopeId $scope.ScopeId | |
# Check Lease Duration | |
if ($PSBoundParameters.ContainsKey('LeaseDurationMinutes') -and ($currentLeaseMinutes -ne $LeaseDurationMinutes)) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'Lease Duration' | |
Current = "$currentLeaseMinutes minutes" | |
New = "$LeaseDurationMinutes minutes" | |
} | |
} | |
# Check DNS Servers | |
if ($ClearDnsSettings -and $currentDnsServers) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'DNS Servers' | |
Current = $currentDnsServers -join ', ' | |
New = 'Cleared' | |
} | |
} | |
elseif ($DnsServers) { | |
$currentDnsString = $currentDnsServers -join ', ' | |
$newDnsString = $DnsServers -join ', ' | |
if ($currentDnsString -ne $newDnsString) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'DNS Servers' | |
Current = if ($currentDnsString) { $currentDnsString } else { 'Not set' } | |
New = $newDnsString | |
} | |
} | |
} | |
# Check DNS Domain | |
if ($ClearDnsDomain -and $currentDnsDomain) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'DNS Domain' | |
Current = $currentDnsDomain | |
New = 'Cleared' | |
} | |
} | |
elseif ($DnsDomain -and $currentDnsDomain -ne $DnsDomain) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'DNS Domain' | |
Current = if ($currentDnsDomain) { $currentDnsDomain } else { 'Not set' } | |
New = $DnsDomain | |
} | |
} | |
# Check DNS Update Settings | |
if ($PSBoundParameters.ContainsKey('DnsUpdateSetting') -and | |
$currentDnsSettings.DynamicUpdates -ne $DnsUpdateSetting) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'DNS Update Setting' | |
Current = $currentDnsSettings.DynamicUpdates | |
New = $DnsUpdateSetting | |
} | |
} | |
# Check PTR Records setting | |
if ($PSBoundParameters.ContainsKey('RegisterPtrRecords') -and | |
$currentDnsSettings.UpdateDnsRRForOlderClients -ne $RegisterPtrRecords) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'Register PTR Records' | |
Current = $currentDnsSettings.UpdateDnsRRForOlderClients | |
New = $RegisterPtrRecords | |
} | |
} | |
# Check Discard Records setting | |
if ($PSBoundParameters.ContainsKey('DiscardRecordsOnExpiry') -and | |
$currentDnsSettings.DeleteDnsRROnLeaseExpiry -ne $DiscardRecordsOnExpiry) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'Discard Records on Expiry' | |
Current = $currentDnsSettings.DeleteDnsRROnLeaseExpiry | |
New = $DiscardRecordsOnExpiry | |
} | |
} | |
# Check Override Client Request setting | |
if ($PSBoundParameters.ContainsKey('OverrideClientRequest') -and | |
$currentDnsSettings.DisableDnsPtrRRUpdate -ne $OverrideClientRequest) { | |
$script:plannedChanges += [PSCustomObject]@{ | |
Scope = $scope.ScopeId | |
Setting = 'Override Client Request' | |
Current = $currentDnsSettings.DisableDnsPtrRRUpdate | |
New = $OverrideClientRequest | |
} | |
} | |
} | |
# If there are changes, show them and process if confirmed | |
if ($script:plannedChanges.Count -gt 0) { | |
Write-Host "`nPlanned changes:" -ForegroundColor Yellow | |
$script:plannedChanges | Format-Table -AutoSize | Out-Host | |
if (-not $PSCmdlet.ShouldProcess("Perform changes")) { | |
return | |
} | |
# Skip confirmation if -Force is used | |
if (-not $Force) { | |
$title = "Confirm Changes" | |
$question = "Do you want to proceed with these changes?" | |
$choices = "&Yes", "&No" | |
$decision = $Host.UI.PromptForChoice($title, $question, $choices, 1) | |
if ($decision -eq 1) { | |
Write-Host "`nOperation cancelled by user" -ForegroundColor Yellow | |
return | |
} | |
} | |
foreach ($scope in $scopes) { | |
Write-Host "----------------------------------------" -ForegroundColor Blue | |
Write-Host "Scope: " -NoNewline | |
Write-Host "$($scope.ScopeId) ($($scope.Name))" -ForegroundColor Yellow | |
Write-Host "----------------------------------------" -ForegroundColor Blue | |
# Update Lease Duration | |
if ($PSBoundParameters.ContainsKey('LeaseDurationMinutes')) { | |
$currentScope = Get-DhcpServerv4Scope -ComputerName $DhcpServer -ScopeId $scope.ScopeId | |
$currentLeaseMinutes = $currentScope.LeaseDuration.TotalMinutes | |
if ($currentLeaseMinutes -ne $LeaseDurationMinutes) { | |
Write-Host "Lease Duration" | |
Write-Host "Current: " -NoNewline | |
Write-Host "$currentLeaseMinutes minutes" -ForegroundColor Gray | |
Write-Host "New : " -NoNewline | |
Write-Host "$LeaseDurationMinutes minutes" -ForegroundColor Green | |
if ($PSCmdlet.ShouldProcess($scope.ScopeId, "Set lease duration to $LeaseDurationMinutes minutes")) { | |
Set-DhcpServerv4Scope -ComputerName $DhcpServer -ScopeId $scope.ScopeId -LeaseDuration (New-TimeSpan -Minutes $LeaseDurationMinutes) | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'LeaseDuration' | |
OldValue = $currentLeaseMinutes | |
NewValue = $LeaseDurationMinutes | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
} | |
} | |
# Update DNS Servers | |
$currentDnsServers = (Get-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 6 -ErrorAction SilentlyContinue).Value | |
Write-Host "`nDNS Servers" | |
Write-Host "Current: " -NoNewline | |
Write-Host "$(if ($currentDnsServers) { $currentDnsServers -join ', ' } else { 'Not set' })" -ForegroundColor Gray | |
if ($ClearDnsSettings -and $currentDnsServers) { | |
Write-Host "New : " -NoNewline | |
Write-Host "Clearing DNS servers" -ForegroundColor Yellow | |
if ($PSCmdlet.ShouldProcess($scope.ScopeId, "Clear DNS servers")) { | |
Remove-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 6 | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'ClearDnsServers' | |
OldValue = $currentDnsServers -join ',' | |
NewValue = $null | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
} | |
elseif ($DnsServers) { | |
$currentDnsString = $currentDnsServers -join ', ' | |
$newDnsString = $DnsServers -join ', ' | |
if ($currentDnsString -ne $newDnsString) { | |
Write-Host "New : " -NoNewline | |
Write-Host "$newDnsString" -ForegroundColor Green | |
if ($PSCmdlet.ShouldProcess($scope.ScopeId, "Set DNS servers to: $newDnsString")) { | |
$dnsParams = @{ | |
ComputerName = $DhcpServer | |
ScopeId = $scope.ScopeId | |
OptionId = 6 | |
Value = $DnsServers | |
} | |
if ($SkipDnsValidation) { | |
$dnsParams.Add('Force', $true) | |
} | |
Set-DhcpServerv4OptionValue @dnsParams | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'SetDnsServers' | |
OldValue = $currentDnsString | |
NewValue = $newDnsString | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
} | |
} | |
# Update DNS Domain | |
$currentDnsDomain = (Get-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 15 -ErrorAction SilentlyContinue).Value | |
Write-Host "`nDNS Domain" | |
Write-Host "Current: " -NoNewline | |
Write-Host "$(if ($currentDnsDomain) { $currentDnsDomain } else { 'Not set' })" -ForegroundColor Gray | |
if ($ClearDnsDomain -and $currentDnsDomain) { | |
Write-Host "New : " -NoNewline | |
Write-Host "Clearing DNS domain" -ForegroundColor Yellow | |
if ($PSCmdlet.ShouldProcess($scope.ScopeId, "Clear DNS domain")) { | |
Remove-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 15 | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'ClearDnsDomain' | |
OldValue = $currentDnsDomain | |
NewValue = $null | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
} | |
elseif ($DnsDomain -and $currentDnsDomain -ne $DnsDomain) { | |
Write-Host "New : " -NoNewline | |
Write-Host "$DnsDomain" -ForegroundColor Green | |
if ($PSCmdlet.ShouldProcess($scope.ScopeId, "Set DNS domain to: $DnsDomain")) { | |
Set-DhcpServerv4OptionValue -ComputerName $DhcpServer -ScopeId $scope.ScopeId -OptionId 15 -Value $DnsDomain | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'SetDnsDomain' | |
OldValue = $currentDnsDomain | |
NewValue = $DnsDomain | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
} | |
# Handle DNS Settings | |
$currentDnsSettings = Get-DhcpServerv4DnsSetting -ComputerName $DhcpServer -ScopeId $scope.ScopeId | |
$dnsSettingsChanged = $false | |
$dnsParams = @{ | |
ComputerName = $DhcpServer | |
ScopeId = $scope.ScopeId | |
} | |
Write-Host "`nDNS Settings" | |
Write-Host "Current settings:" | |
Write-Host "- DNS Updates: " -NoNewline | |
Write-Host $currentDnsSettings.DynamicUpdates -ForegroundColor Gray | |
Write-Host "- Register PTR: " -NoNewline | |
Write-Host $currentDnsSettings.UpdateDnsRRForOlderClients -ForegroundColor Gray | |
Write-Host "- Discard on Expiry: " -NoNewline | |
Write-Host $currentDnsSettings.DeleteDnsRROnLeaseExpiry -ForegroundColor Gray | |
Write-Host "- Override Client: " -NoNewline | |
Write-Host $currentDnsSettings.DisableDnsPtrRRUpdate -ForegroundColor Gray | |
if ($PSBoundParameters.ContainsKey('DnsUpdateSetting')) { | |
$dnsParams['DynamicUpdates'] = $DnsUpdateSetting | |
$dnsSettingsChanged = $true | |
} | |
if ($PSBoundParameters.ContainsKey('RegisterPtrRecords')) { | |
$dnsParams['UpdateDnsRRForOlderClients'] = $RegisterPtrRecords.IsPresent | |
$dnsSettingsChanged = $true | |
} | |
if ($PSBoundParameters.ContainsKey('DiscardRecordsOnExpiry')) { | |
$dnsParams['DeleteDnsRROnLeaseExpiry'] = $DiscardRecordsOnExpiry.IsPresent | |
$dnsSettingsChanged = $true | |
} | |
if ($PSBoundParameters.ContainsKey('OverrideClientRequest')) { | |
$dnsParams['DisableDnsPtrRRUpdate'] = $OverrideClientRequest.IsPresent | |
$dnsSettingsChanged = $true | |
} | |
if ($dnsSettingsChanged) { | |
Write-Host "`nApplying new DNS settings..." -ForegroundColor Yellow | |
if ($PSCmdlet.ShouldProcess($scope.ScopeId, "Update DNS settings")) { | |
Set-DhcpServerv4DnsSetting @dnsParams | |
# Get updated settings for verification and output | |
$newDnsSettings = Get-DhcpServerv4DnsSetting -ComputerName $DhcpServer -ScopeId $scope.ScopeId | |
# Compare and create individual records for each changed setting | |
if ($PSBoundParameters.ContainsKey('DnsUpdateSetting') -and | |
$currentDnsSettings.DynamicUpdates -ne $newDnsSettings.DynamicUpdates) { | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'DynamicUpdates' | |
OldValue = $currentDnsSettings.DynamicUpdates | |
NewValue = $newDnsSettings.DynamicUpdates | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
if ($PSBoundParameters.ContainsKey('RegisterPtrRecords') -and | |
$currentDnsSettings.UpdateDnsRRForOlderClients -ne $newDnsSettings.UpdateDnsRRForOlderClients) { | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'RegisterPtrRecords' | |
OldValue = $currentDnsSettings.UpdateDnsRRForOlderClients | |
NewValue = $newDnsSettings.UpdateDnsRRForOlderClients | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
if ($PSBoundParameters.ContainsKey('DiscardRecordsOnExpiry') -and | |
$currentDnsSettings.DeleteDnsRROnLeaseExpiry -ne $newDnsSettings.DeleteDnsRROnLeaseExpiry) { | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'DiscardRecordsOnExpiry' | |
OldValue = $currentDnsSettings.DeleteDnsRROnLeaseExpiry | |
NewValue = $newDnsSettings.DeleteDnsRROnLeaseExpiry | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
if ($PSBoundParameters.ContainsKey('OverrideClientRequest') -and | |
$currentDnsSettings.DisableDnsPtrRRUpdate -ne $newDnsSettings.DisableDnsPtrRRUpdate) { | |
$script:changes += [PSCustomObject]@{ | |
ScopeId = $scope.ScopeId | |
ScopeName = $scope.Name | |
ChangeType = 'OverrideClientRequest' | |
OldValue = $currentDnsSettings.DisableDnsPtrRRUpdate | |
NewValue = $newDnsSettings.DisableDnsPtrRRUpdate | |
TimeStamp = (Get-Date) | |
ServerName = $DhcpServer | |
Description = $scope.Description | |
} | |
} | |
Write-Host "New settings applied:" -ForegroundColor Green | |
Write-Host "- DNS Updates: " -NoNewline | |
Write-Host $newDnsSettings.DynamicUpdates -ForegroundColor Green | |
Write-Host "- Register PTR: " -NoNewline | |
Write-Host $newDnsSettings.UpdateDnsRRForOlderClients -ForegroundColor Green | |
Write-Host "- Discard on Expiry: " -NoNewline | |
Write-Host $newDnsSettings.DeleteDnsRROnLeaseExpiry -ForegroundColor Green | |
Write-Host "- Override Client: " -NoNewline | |
Write-Host $newDnsSettings.DisableDnsPtrRRUpdate -ForegroundColor Green | |
} | |
} | |
Write-Host "----------------------------------------" -ForegroundColor Blue | |
Write-Host "" | |
} | |
Write-Host "`nConfiguration update completed successfully!`n" -ForegroundColor Green | |
} | |
else { | |
Write-Host "`nNo changes required" -ForegroundColor Green | |
} | |
} | |
catch { | |
Write-Host "`nError occurred: " -ForegroundColor Red -NoNewline | |
Write-Host "$_`n" -ForegroundColor Red | |
throw $_ | |
} | |
} | |
end { | |
if ($script:changes.Count -gt 0) { | |
$script:changes | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment