Desired State Configuration (DSC) Nodes Deployment and Conformance Reporting Series (Part 2): Deploying a pull service endpoint and automating the configuration of the DSC nodes

In this post, we will cover how a pull service endpoint can be installed, and how nodes can be configured to point to this server and retrieve their DSC configurations.

There are already a few blog posts regarding the installation of the pull service endpoint, including this post that shows a snippet on how to deploy pull service and conformance endpoints via a DSC configuration…So, you might wonder why we’re having a new one here!

Well, today’s post…

  • includes an updated working snippet that combines both deployments (pull service endpoint and conformance endpoint), also updated to include the needed Windows Authentication dependencies that have been discussed in the blog comments
  • also covers one example of how to overcome one of the challenges when configuring nodes for pull service endpoint, which is managing the GUIDs for the nodes.

So, Here are the steps we are going to go through in this post:

  1. Check prerequisites to install the pull service endpoint
  2. Deploy/configure the pull service endpoint
  3. Provisioning configurations for the nodes
  4. Configuring the nodes to point to the pull service endpoint
  5. Checking nodes are applying the configuration
    • We’ll do this last step manually and on a single node in this post, and then move to the capabilities offered by the conformance endpoint to do this at scale in a larger environment, in the 3rd blog post

Checking prerequisites to install the pull service endpoint

Windows Management Framework (WMF) 4.0 is a prerequisite to leverage DSC so, to make things easier, we will be deploying our pull service and conformance endpoints on a Windows Server 2012 R2 machine, which includes WMF 4.0 out of the box.

You will also need the DSC Resource Kit from this link.

The DSC Resource Kit comes as a zipped package, and you just have to copy its content into the $env:ProgramFiles\WindowsPowerShell\Modules folder on the future pull/conformance server.


Configuring the pull service endpoint

Here is the script you would need to run on the server, from ISE for example. In our situation, this was run on a server called DSCSERVER, as seen in line 54.

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059 configuration Sample_xDscWebService { param ( [string[]]$NodeName = 'localhost', [ValidateNotNullOrEmpty()] [string] $certificateThumbPrint = "AllowUnencryptedTraffic" ) Import-DSCResource -ModuleName xPSDesiredStateConfiguration Node $NodeName { WindowsFeature DSCServiceFeature { Ensure = "Present" Name = "DSC-Service" } WindowsFeature WinAuth { Ensure = "Present" Name = "web-Windows-Auth" } xDscWebService PSDSCPullServer { Ensure = "Present" EndpointName = "PullSvc" Port = 8080 PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\PSDSCPullServer" CertificateThumbPrint = $certificateThumbPrint ModulePath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules" ConfigurationPath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration" State = "Started" DependsOn = "[WindowsFeature]DSCServiceFeature" } xDscWebService PSDSCComplianceServer { Ensure = "Present" EndpointName = "DscConformance" Port = 9090 PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\PSDSCComplianceServer" CertificateThumbPrint = "AllowUnencryptedTraffic" State = "Started" IsComplianceServer = $true DependsOn = @("[WindowsFeature]DSCServiceFeature","[WindowsFeature]WinAuth","[xDSCWebService]PSDSCPullServer") } } } Sample_xDscWebService -ComputerName "DSCSERVER"Start-DscConfiguration -Wait -Verbose .\Sample_xDscWebService

A few notes regarding this script:

  • This configuration simultaneously deploys the conformance endpoint that we will use later in the blog post series, to see how the nodes are doing when downloading and applying their assigned DSC configurations.
  • The conformance endpoint uses Windows Authentication and therefore the WinAuth Windows feature needs to be installed. In our configuration script, we used the DependsOn property to take care of the dependencies for the conformance endpoint
  • Note that the xDSCWebService still refers to the conformance endpoint as “compliance endpoint” (and actually enforces it in the URL, even if you were to rename PSDSCComplianceServer to another value). DSC components are being transitioned to the updated “conformance endpoint” name, that we prefer to use now and throughout this blog post series.
  • Finally, the last few lines are just here to apply the configuration.

Here is the output of the script running, with the future URIs highlighted, for the two web services:

image

 

We can also see that the content for the two websites has been created in the WWWROOT folder on the server:

image

Finally, running Get-DscConfiguration shows that the configuration has been applied, if we still had any doubts Smile

image


Provisioning configurations for the DSC nodes

On the DSC server, here is a script that will do the following:

- Line 21: The script receives a list of nodes to configure – In this sample, this is in the form of an array, but you could very well query Active Directory, a CMDB, a custom database, etc.

- Lines 23-30: For each node, it does generate a GUID that will be used to make this configuration unique for each node, generates a MOF file for each node.

  • The configuration applied is here called “TestConfig” and is detailed at lines 1-19. This is just a very basic sample configuration that ensures that the content of a shared folder is copied locally to the temp folder on the local node
  • Also note how the Node/GUID association is added to a CSV file at line 29. This will be important when we configure the node at the next step, and is there to ensure the node has a location to query its GUID when configuring its LCM, without any manual intervention. The CSV approach makes it easy to show the content as a blog post sample, needless to say that leveraging a database or a more reliable/secure approach would be preferred, as discussed in the community.

- Line 32-39: A checksum is generated for each file, and all files generated are copied to the pull service configuration store, so that they are made available for the future nodes

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042 Configuration TestConfig { Param( [Parameter(Mandatory=$True)] [String[]]$NodeGUID ) Node $NodeGUID { File ScriptPresence { Ensure = "Present" Type = "Directory" Recurse = $True SourcePath = "\\storagebox\SourceFiles\SCCM Toolkit" DestinationPath = "C:\Temp\DSCTest" } }}$Computers = @("DSCNODE1", "DSCNODE2")write-host "Generating GUIDs and creating MOF files..."foreach ($Node in $Computers) { $NewGUID = [guid]::NewGuid() $NewLine = "{0},{1}" -f $Node,$NewGUID TestConfig -NodeGUID $NewGUID $NewLine | add-content -path "$env:SystemDrive\Program Files\WindowsPowershell\DscService\Configuration\dscnodes.csv" }write-host "Creating checksums..."New-DSCCheckSum -ConfigurationPath .\TestConfig -OutPath .\TestConfig -Verbose -Forcewrite-host "Copying configurations to pull service configuration store..."$SourceFiles = (Get-Location -PSProvider FileSystem).Path + "\TestConfig\*.mof*"$TargetFiles = "$env:SystemDrive\Program Files\WindowsPowershell\DscService\Configuration"Move-Item $SourceFiles $TargetFiles -ForceRemove-Item ((Get-Location -PSProvider FileSystem).Path + "\TestConfig\")

When the script runs, it creates the MOF files and shows the checksums (because of the –Verboseswitch):

image

The files are present in the DSC pull service configuration store, including our CSV file:

image

And here is the content of the CSV file:

image


 

Applying configuration on the DSC nodes

The goal here will be to be as dynamic as possible, so that a single generic PS1 file could be sent to the DSC nodes, and “discover” the configuration to apply. The script could be send via the method of your choice, including software distribution tools like Configuration Manager as part of the System Center suite.

Here is the script we will be using:

001002003004005006007008009010011012013014015016017018019020021022023024025026027028 Configuration SimpleMetaConfigurationForPull { Param( [Parameter(Mandatory=$True)] [String]$NodeGUID ) LocalConfigurationManager { ConfigurationID = $NodeGUID; RefreshMode = "PULL"; DownloadManagerName = "WebDownloadManager"; RebootNodeIfNeeded = $true; RefreshFrequencyMins = 15; ConfigurationModeFrequencyMins = 30; ConfigurationMode = "ApplyAndAutoCorrect"; DownloadManagerCustomData = @{ServerUrl = "https://DSCSERVER.contoso.com:8080/PullSvc/PSDSCPullServer.svc"; AllowUnsecureConnection = “TRUE”} } } $data = import-csv "\\dscserver\c$\Program Files\WindowsPowershell\DscService\Configuration\dscnodes.csv" -header("NodeName","NodeGUID")SimpleMetaConfigurationForPull -NodeGUID ($data | where-object {$_."NodeName" -eq $env:COMPUTERNAME}).NodeGUID -Output "." $FilePath = (Get-Location -PSProvider FileSystem).Path + "\SimpleMetaConfigurationForPull"Set-DscLocalConfigurationManager -ComputerName "localhost" -Path $FilePath -Verbose

Some important parts of the scripts are:

- The configuration (lines 1-20): This set the LCM for pull mode, and specifies which pull service endpoint to use. It also specifies if we should just monitor DSC configurations, or try to auto correct them. In this sample, we apply and auto-correct. The frequency is also specified here.

- In the configuration, note that we need to specify the GUID for the ConfigurationID parameter. This is why we created that CSV file, so that the script can “discover” which GUID to use, at lines 22 and 24.

  • Note: The CSV file is directly accessed via the administrative share, to keep things simple in this sample. In reality, it would likely be on a secured shared elsewhere. Or, as we discussed earlier, you might be using a custom database or a CMDB to store this data instead of this CSV sample.

- The LCM configuration is compiled at line 30 and applied at line 32

 

This is the output of the script running on a node:

image

When we display the LCM configuration, we can see that the pull service endpoint is now configured in the LCM:

image


Checking that configurations are being applied to nodes

After the interval (or, for testing purposes, you can force things with a reboot, or via scripting), we can see the configuration pulled, in the event log – This is for the node called DSCNODE1, and you can see how the GUID matches what we had previously.

image

Note how the node did not need to pull specific modules in this case, but the pull service endpoint can provide modules when a node needs them to apply a specific configuration.

image

Finally, we can confirm that the folder was created, with content copied by DSC. And if we were to delete this folder, it will be copied again by DSC.

image

Note : You can also leverage the xDscDiagnostics module for some of these, as needed.

We’ve now checked that everything is working on a single node. In the next post in this series, we will look at how the conformance endpoint can be used to look at the status of configuration downloads/applications across nodes.


Blog post series agenda

  1. Series agenda, Understanding the DSC conformance endpoint
  2. How to deploy a pull service endpoint and automate the configuration of the DSC nodes (this post)
  3. How to leverage the conformance endpoint deployed along with part of the pull service endpoint, to report on accurate configuration deployment and application: Are my DSC nodes downloading and applying the configurations without encountering any errors?
  4. Some options to determine if the nodes are conformant with the given configuration: Are my DSC nodes conformance with the configuration they are supposed to enforce?