Background

Previously I’ve discussed using DSC in a push configuration where by an administrator applies configuration changes to a node by compiling a DSC script into a MOF (Managed Object File) and running Start-DSCConfiguration against a target node from their workstation.

Pushing DSC configuration is hardly zero-touch as it relies on someone somewhere to do something. If you want nodes to automatically retrieve and apply their configuration changes, you need a DSC pull server.

Note: This is an old article and may contain content which is out of date.

I’m currently tasked with implementing a DSC Pull server to provision our developer workstations. This article covers what I’ve learned thus far when it comes to running a DSC pull configuration. If you’re following this as a tutorial, your DSC pull server will be a running at Windows Server 2008 r2 with at least Windows Management Framework 4.0 installed.

Installing and Configuring the DSC Pull Server

We will use a DSC script that will configure a DSC pull server. Before we do so, we need to install the required DSC Resources. You will need to download and install the xPSDesiredStateConfiguration module. If you aren’t sure how to do this, have a look at the resources section section in the previous article. Don’t forget you need to make this DSC resource available on both your DSC pull server and the workstation from which you will be applying the configuration.

Once you have that module installed, you can use a PowerShell to install the DSC Web Service and configure your DSC pull server. Firstly run the following script to define a DSC configuration. (Hint: If you have the script file saved, you can run it by dot sourcing the script file, e.g. . ./myDscScripts/DSCPullServer.ps1)

Configuration DSCPullServer
{   	
	Import-DSCResource -ModuleName xPSDesiredStateConfiguration
	
	Node <YourDSCServer>
	{
        WindowsFeature DSCServiceFeature
        {
            Ensure = "Present"
            Name = "DSC-Service"
        }
		
        xDscWebService  DSCPullServer
        {
            Ensure = "Present"
            EndPointName = "DSCPullServer"
            Port = 8080
            PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\DSCPullServer"
            CertificateThumbPrint = "AllowUnencryptedTraffic"
            ModulePath = "C:\DSCPullServer\Modules"
            ConfigurationPath = "C:\DSCPullServer\Configuration"
            State = "Started"
            DependsOn = "[WindowsFeature]DSCServiceFeature"
        }
		
        xDscWebService  DSCComplianceServer
        {
            Ensure = "Present"
            EndPointName = "DSCComplianceServer"
            Port = 8081
            PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\DSCComplianceServer"
            CertificateThumbPrint = "AllowUnencryptedTraffic"
            State = "Started"
            IsComplianceServer = $true
            DependsOn = "[WindowsFeature]DSCServiceFeature"
        }
    }
}

Substitute <YourDSCServer> for the name of the server that will run your DSC Service. Note that at this stage, we’re setting up our server to use an unencrypted HTTP web service.

Run the above DSC configuration to create a managed object file:

PS \> DSCPullServer

Then apply your configuration with the Start-DSCConfiguration commandlet:

PS \> Start-DSCConfiguration -Path .\DSCPullServer -verbose -wait

Once the configuration job is complete, you should have a working DSC pull server. You can check this quickly and easily using a web browser:

1

Creating DSC Configuration

At this stage we’re ready to create a DSC configuration file that will be applied to a nodes configured to use the push server to obtain its configuration. My starting point might be a simple DSC script that installs IIS:

Configuration IisWebServer
{
    Node 8f5016dc-052c-4a01-9c84-8dcea37c9ab1 
    {
        WindowsFeature IIS
        {
            Ensure="Present"
            Name="Web-Server"
        }
        WindowsFeature Mgmt-Tools 
        {
            Ensure 	= "Present"
            Name	= "Web-Mgmt-Tools" 
        }
        WindowsFeature Mgmt-Console 
        {
            Ensure 	= "Present"
            Name	= "Web-Mgmt-Console" 
        }
        WindowsFeature Mgmt-Service 
        {
            Ensure 	= "Present"
            Name	= "Web-Mgmt-Service" 
        }

    }
}

You will notice one distinct difference between this DSC script and those created in the last article for use in the push configuation. Instead of “Node” specifying the hostname of target computer name, I’m using a GUID. You will see how this is used later, but in the meantime generating a GUID for use in a pull configuration is quick and easy using PowerShell:

PS \> [guid]::NewGuid()
8f5016dc-052c-4a01-9c84-8dcea37c9ab1

We now need to create a managed object file from our configuration. Simply execute the DSC script (by either pressing F5 in the PowerShell Integrated Scripted Environment or dot sourcing in the script file, as per the earlier example). Then execute the dsc function:

PS \> IisWebServer

This will create a folder in your current directory called “IisWebServer”. The folder will contain a managed object file named for the GUID used in your DSC script. Now we need to create a checksum that we will store with our managed object file.

PS \> New-DSCChecksum -ConfigurationPath .\IisWebServer -OutPath .\IisWebServer -Verbose -Force

Now we can copy the configuration file and the checksum to the DSC Pull Server

PS \>  Copy-Item -Path .\IisWebServer\* -Destination \\win2k12r2-dc1\c$\DSCPullServer\Configuration\

Configuring a Node to use the DSC Pull Server

Finally, we need to tweak the local configuration manager on a DSC client node to use the pull server we’ve just set-up. For this we write another DSC script:

Configuration SetPullMode
{
    Node <NodeName>
    {
        LocalConfigurationManager
        {
            # Necessary to push updates to the compliance server
            ConfigurationMode = 'ApplyAndAutocorrect' 		

            # For testing purposes - means we don't have to wait long
            RefreshFrequencyMins = 5

            ConfigurationID = "8f5016dc-052c-4a01-9c84-8dcea37c9ab1"
            RefreshMode = ‘Pull’
            DownloadManagerName = ‘WebDownloadManager’
            DownloadManagerCustomData = @{
                ServerUrl = ‘http://PullServerName>/PSDSCPullServer.svc/’;
                AllowUnsecureConnection = ‘true’ }
            AllowModuleOverwrite = 'True'
        }
    }
}
PS \>  SetPullMode
PS \>  Set-DSCLocalConfigurationManager –ComputeName <NodeName> -Path ./SetPullMode –Verbose

There’s a few things to note here:

  • <NodeName> needs substituting for the host named of the node that is being configured to use our DSC Pull Server
  • <PullServerName> should be subsituted for the hostname or DNS name of the server we’ve set-up with the DSC Web Service
  • The DSC compliance server is updated by a client when it refreshes it’s configuration, as oppose to when DSC pull configuration is applied. This means that setting “ConfigurationMode” to “Apply” results in a compliance server that’s never updated.
  • It’s possible to give the same ConfigurationID to multiple clients without affecting the application of desired state configuration or reporting through the compliance server

Five or so minutes after configuring our DSC client to use the pull server, we should see the IIS role has been installed.