Configuration data supplies static values and parameters to automation without containing executable commands. Separating inputs from PowerShell functions lets one script apply different server settings while keeping implementation reusable and testable. section 6.3 section 6.3.4
A practical configuration-driven automation follows this sequence:
- Define reusable functions for tasks such as installing Windows Features, setting firewall defaults, and checking or resolving registry values. section 6.3
- Generate or maintain a JSON file containing the parameters required by those functions. section 6.3 section 6.3.3
- Import the JSON with Get-Content and ConvertFrom-Json, convert it to a ServerConfig object, and call functions in the required order. section 6.3.2
- Log returned results and, for compliance checks, verify settings, apply fixes, and verify them again. section 6.3.2
- Store configurations in a module's Configurations folder and select one by name or through Out-GridView. section 6.3.3
Static date parameters instead of commands
Store an integer such as AddYears = 1, create the DateTime value inside the script, and pass the parameter to AddYears(). Do not store '(Get-Date).AddYears(1)' and evaluate it with Invoke-Expression; command-bearing data complicates testing and can enable injection attacks. section 6.3.4
Listing 6.14 Set-ServerConfig
Function Set-ServerConfig {
[CmdletBinding()]
[OutputType([object])]
param(
[Parameter(Mandatory = $true)]
[object]$ConfigJson,
[Parameter(Mandatory = $true)]
[object]$LogFile
)
$JsonObject = Get-Content $ConfigJson -Raw | #1
ConvertFrom-Json
$Config = [ServerConfig]::new($JsonObject) #2
Function Write-StartLog { #3
param(
$Message
)
"`n$('#' * 50)`n# $($Message)`n" | Out-File $LogFile -Append
Write-Host $Message
}
Function Write-OutputLog { #4
param(
$Object
)
$output = $Object | Format-Table | Out-String
if ([string]::IsNullOrEmpty($output)) {
$output = 'No data'
}
"$($output.Trim())`n$('#' * 50)" | Out-File $LogFile -Append
Write-Host $output
}
$msg = "Start Server Setup - $(Get-Date)`nFrom JSON $($ConfigJson)"
Write-StartLog -Message $msg
Write-StartLog -Message "Set Features" #5
$Features = Install-RequiredFeatures -Features $Config.Features
Write-OutputLog -Object $Features
Write-StartLog -Message "Set Services" #6
$WindowsService = @{
Services = $Config.Services
HardKillSeconds = 60
SecondsToWait = 90
}
$Services = Disable-WindowsService @WindowsService
Write-OutputLog -Object $Services
Write-StartLog -Message "Set Security Baseline"
foreach ($sbl in $Config.SecurityBaseline) { #7
$sbl = Test-SecurityBaseline $sbl
}
foreach ($sbl in $Config.SecurityBaseline | #8
Where-Object { $_.Success -ne $true }) {
Set-SecurityBaseline $sbl
$sbl = Test-SecurityBaseline $sbl
}
$SecLog = $SecBaseline |
Select-Object -Property KeyPath, Name, Data, Result, SetValue
Write-OutputLog -Object $SecLog
Write-StartLog -Message "Set Firewall" #9
$Firewall = Set-FirewallDefaults -LogSize $Config.FirewallLogSize
Write-OutputLog -Object $Firewall
Write-Host "Server configuration is complete."
Write-Host "All logs written to $($LogFile)"
}
The complete orchestration function demonstrates importing JSON, constructing configuration data, logging results, and coordinating configuration tasks. section 6.3.2






















