Select Page

If you’ve been following my blog, you know I’ve become a big fan of the new Desired State Configuration feature in Windows Management Framework 4 (i.e. PowerShell 4). It makes configuring Windows Servers a snap and provides a whole new set of configuration flexibility, above and beyond what you can get from Group Policy today. One of the exercises I’ve been working on recently is how to help customers transition from Group Policy to DSC. And to that end, the PowerShell script within this blog posting will take Administrative Template settings from within a GPO, and automatically generate a DSC configuration document with all of those settings. There’s a few things to note about this script and its capabilities:

  1. The script leverages the get-gpregistryvalue cmdlet from the Microsoft Group Policy PowerShell module. This module gets installed when the Group Policy Management Console (GPMC) is installed so it’s a pre-requisite for getting this to work
  2. The script currently only exports out per-computer (i.e. Computer Configuration\Policies\Administrative Templates) settings. At the moment, DSC is really optimized for per-computer configuration. It’s easy enough to modify the script if you want to get the per-user Admin Template settings in a GPO, but this script isn’t doing that.
  3. The script pulls ALL per-computer Administrative Template settings from the GPO you specify. There’s currently no way to pick and choose the settings you want–at least not during the generation phase. You can always remove settings from the resulting DSC configuration document.
  4. The script uses the DSC Registry resource to create entries in the DSC document. The Registry resources, by default, get the name of the registry value that is being set. This is a limitation of the Get-GPRegistryValue cmdlet–it doesn’t retrieve the “friendly name” of the policy setting, as it would appear in the underlying ADM/ADMX file. I’m working on a more friendly process using our Group Policy Automation Engine but as of right now, the script doesn’t do this.
  5. The script pulls Admin Template settings out of a GPO. It’s important to note that Group Policy does provide one big advantage over DSC. Namely, when a policy that delivers Administrative Template settings is removed, those registry settings are “un-tattooed” from the target system. Essentially, they are automatically removed. This doesn’t happen when registry policy is delivered via DSC. The policies are set in the same location as they would be via Group Policy, but there is no notion of tattooing and un-tattooing in DSC. A configuration is either in place according to the document, or it’s not. Therefore, if you wanted to undo registry policy settings using DSC, you would need to edit the configuration document that sets those registry policies, change the “Ensure” property of each registry resource to “Absent” and re-apply that document to your target systems.

So, without further ado, here’s the script:
[codebox lang=”ps”]
param
(
[string]$gpoName,
[string] $outputFolder
)

function ADMtoDSC
{
param
(
[String] $gpo,
[String] $path
)
$policies = Recurse_PolicyKeys -key “HKLM\Software\Policies” -gpo $gpo

$policies += Recurse_PolicyKeys -key “HKLM\Software\Microsoft\Windows NT\CurrentVersion” -gpo $gpo
#build the DSC configuration doc
GenConfigDoc -path $path -gpo $gpo -policies $policies
}

function Recurse_PolicyKeys
{
param
(
[string]$key,
[string]$gpoName

)
$current = Get-GPRegistryValue -Name $gpo -Key $key
foreach ($item in $current)
{
if ($item.ValueName -ne $null)
{
[array]$returnVal += $item
}
else
{
Recurse_PolicyKeys -Key $item.FullKeyPath -gpoName $gpo
}
}
return $returnVal
}
function GenConfigDoc
{
param
(
[string] $path,
[string] $gpo,
[array] $policies
)
#parse the spaces out of the GPO name, since we use it for the Configuration name
$gpo = $gpo -replace ” “,”_”
$outputFile = “$path\$gpo.ps1”
“Configuration `”$gpo`”” | out-file -FilePath $outputFile
‘{‘ | out-file -FilePath $outputFile -Append
‘Node localhost’ | out-file -FilePath $outputFile -Append
‘ {‘ | out-file -FilePath $outputFile -Append
foreach ($regItem in $policies)
{
if ($regItem.FullKeyPath -eq $null) #throw away any blank entries
{
continue
}
#now build the resources
” Registry `”” + $regItem.ValueName + “`””| out-file -FilePath $outputFile -Append
‘ {‘ | out-file -FilePath $outputFile -Append
” Ensure = `”Present`”” | out-file -FilePath $outputFile -Append
” Key = `””+ $regItem.FullKeyPath + “`””| out-file -FilePath $outputFile -Append
” ValueName = `”” + $regItem.ValueName + “`”” | out-file -FilePath $outputFile -Append
” ValueType = `”” +$regItem.Type + “`”” | out-file -FilePath $outputFile -Append
” ValueData = `”” +$regItem.Value + “`””| out-file -FilePath $outputFile -Append
‘ }’ | out-file -FilePath $outputFile -Append
}
‘ }’ | out-file -FilePath $outputFile -Append
‘}’ | out-file -FilePath $outputFile -Append
$gpo | out-file -FilePath $outputFile -Append
write-host “DSC document written to $outputFile”
}

ADMToDSC -gpo $gpoName -path $outputFolder

[/codebox]

So when you save this to a .ps1 file and call this script, it will look like this:

.\ADMToDSC.ps1 -gpoName “Admin Template GPO” -outputFolder c:\dsc

Where the gpoName parameter is the friendly name of the GPO that you wish to grab Admin Template settings from and the outputFolder parameter is a file system folder where the resulting DSC document is written.
The resulting DSC configuration document will get written to the output folder with a file name will be the name of the GPO that you are exporting from, with a .ps1 extension.

So, check out the script and let me know what you think. Feedback is more than welcome. The process of generating the DSC document is pretty rough and could be more elegant, but it gets the job done.

Darren