Select Page

I wanted to write this post back in December when WMF 5.0 got released but I decided to put it off because a week after release, Microsoft removed the packages from the Download Center because of a nasty bug that reset the PSModulePath settings to default (blog post). So after a two months wait, Microsoft re-released the WMF 5 packages that contain the PSModulePath fix which you can get from here. If you installed WMF 5 before it got pulled, you will have to uninstall KB3094174, KB3094175, and KB3094176 and then install the new ones that just got published.

With this release, users that have not upgraded to Windows 10 due to various reasons and decided to stay on Windows 7 or Windows 8/8.1, now have the possibility of using PowerShell 5.0 and they can now use this package to install PowerShell 5 on Windows Server 2012 R2, Windows Server 2012, Windows 2008 R2 SP1

So what’s new in WMF 5.0?

Just Enough Administration (JEA)
Creating Custom Types using PowerShell Classes
Improvements in PowerShell Script Debugging
Improvements in Desired State Configuration (DSC)
Audit PowerShell Usage using Transcription and Logging
Software Discovery, Install and Inventory with PackageManagement
PowerShell Module Discovery, Install and Inventory with PowerShellGet
PowerShell Script Discovery, Install and Management with PowerShellGet
New and updated cmdlets based on community feedback
Information Stream
Generate PowerShell Cmdlets based on OData Endpoint
Network Switch Management with PowerShell
Software Inventory Logging (SIL)

You can read more about it here: https://msdn.microsoft.com/en-us/powershell/wmf/releasenote

Now this is just a part of what WMF 5.0 bring to the table, the PowerShell team worked a lot on this release, and if you take the time and check you the link that I referenced above, you will find out that what I quoted is just the tip of the iceberg 🙂

In a previous article, I talked about installing and configuring DSC on a Linux machine where I mentioned the methods we have available in order to send out the configurations that we write to the client servers. The first method is Push, where you write a configuration on your local machine, generate the MOF file by calling the configuration like a function and then by using the Start-DscConfiguration -Path cmdlet, you can send the configuration you just wrote to the target machine, telling the Local Configuration Manager to apply the configuration you just wrote. The second method is Pull, where you configure an IIS server to be a OData endpoint that target machines’s LCM can contact, pull the configuration files, resource modules and then apply them.

Here’s the catch; By default, Windows Client and Windows Server operating systems come with just a handful of DSC resources (which you can see below) that can help you do some basic operations but if you want to do more advanced stuff like configure the Windows Firewall or install System Center, then you will have to go to the PowerShell Gallery where you will have to download the resources you’re looking for, and install them on the sender / target machines.

DSCBaseResources

With WMF 5.0, going to the PowerShell Gallery is not mandatory because you can use the cmdlets from the PowerShellGet module to find and install what you’re looking for. The cmdlets that we are interested at this moment are Find-DSC Resource and Install-Module. By running the Find-DscResource cmdlet, you can see all the DSC resources that are available and trust me there are a lot of resources, just check it out, you will be amazed.
Now before you start installing DSC Resources, you need to know one simple thing. Once you run the Find-DSCResource cmdlet, you will see resources that start with an X or a C.

X stands for Experimental, which means that those resources are not yet considered stable and breaking changes can occur at any time and C stands for Community, which means that these resources are made and uploaded to gallery by the community. If you don’t trust any of the resources that are available on the PowerShell Gallery, you still have the option of using the Save-Module cmdlet where you can simply save the module on your system, and analyze it to see if everything is in order before you start playing with it and rolling it out.

Now with that out the way. Here’s one gotcha with the Push method; In order to say, configure a Hyper-V Cluster with DSC using the Push method, you will have to first install the modules locally then install them on the nodes you want to configure to be a cluster, which can get tedious after some time. This is the part where Pull makes a lot of sense. Not only you publish the configuration files on the Pull server, you also put the resource there as well, because if the target system does not have the necessary resources to make it so, it will contact the Pull server and get them. So no more manual copying of stuff. You can go even further with this scenario, you can make baseline configurations like base OS configurations of registry, firewall, network, security etc. that apply to all of managed servers and then you come with a specialized configuration dedicated for web servers, clusters, SharePoint farms and so on.

In a nutshell, when you get a new server be it physical or virtual, you tell the LCM what the server should be and while you’re watching your favorite series and eating pizza, the server will start configuring itself and remain that way until you tell it otherwise. As Jeffrey Snover would put it “Treat your servers like cattle“, write once, apply everywhere.

So without further ado, let’s start building that DSC Pull Server.

There are two types of Pull servers; Web and SMB Pull Server. In this post we will be talking about the web one. The IIS DSC Pull server is the most preferred solution to deploy because besides being a pull server, you also get reporting capabilities, it’s easier to load balance and make it available to DMZ servers without modifying the firewall rules.

In order to get a Pull server up and running we will need a domain joined Windows Server 2012 R2 machine with the latest updates and WMF 5 installed, the DSC Resource xPSDesiredStateConfiguration which you can get from the PowerShell Gallery by running Install-Module xPSDesiredStateConfiguration and PKI in place for secure HTTPS communications. If you don’t have PKI deployed in your infrastructure, then for the love of God, start rolling it out. You even have a DSC resource for that called xAdcsDeployment.
You can in the end run a Pull server without using certificates, but you don’t want credentials and authentication tokens to be sent out in plain text don’t you? In a dev/test environment it’s fine to run without PKI but you really need it when you start deploying in production.

For this occasion, I created a new environment on my Hyper-V server which anybody can set up if they have eight gigabytes of RAM:

VMCapture

Now here are the necessary PowerShell commands and DSC configuration in order to get your started with a Pull server in your dev environment:

On the target machine, you start PowerShell ISE then you install the xPSDesiredStateConfiguration resource and you create a self signed certificate that will be used by the Pull Server.

After that you start writing the configuration that will transform that bare OS instance into a pull server.

ModulePath will be the place where you will store all the DSC resources that you want to be available to the target clients. Now, you don’t simply store the resources in the ModulePath. The entire module needs to be zipped and have a checksum created for it and the reason is that there’s a naming convention created by Microsoft that must be respected. So filename should be in the format of .zip and it has to have a checksum file that can be created using the New-DscChecksum cmdlet and have them stored in the ModulePath folder.
Here’s an example:

xNetworking_2.7.0.0.zip
xNetworking_2.7.0.0.zip.checksum

You can get the module version by running Get-DscResource cmdlet.

ConfigurationPath is where you store your .mof and mof.checksum files.

The Port, PhysicalPath, ModulePath, ConfigurationPath and RegistrationKeyPath can be what ever you want and the AcceptSelfSignedCertificates parameter is not necessary if you’re setting it up in production. If you want to test it out without any type of certificate then you can replace the value from CertificateThumbPrint with “AllowUnencryptedTraffic”

Once you start the configuration, you can go grab a coffee because it will take a bit, depending if the VM is on SSDs or HDDs but once it’s done, you should see something like this:

Mode LastWriteTime Length Name
—- ————- —— —-
-a—- 2/24/2016 6:09 PM 3308 localhost.mof
VERBOSE: Perform operation ‘Invoke CimMethod’ with following parameters, ”methodName’ = SendConfigurationApply,’className’ = MSFT_DSC
LocalConfigurationManager,’namespaceName’ = root/Microsoft/Windows/DesiredStateConfiguration’.
VERBOSE: An LCM method call arrived from computer DSC-PULL with user sid S-1-5-21-1972588538-2743513118-1431156491-500.
VERBOSE: [DSC-PULL]: LCM: [ Start Set ]
VERBOSE: [DSC-PULL]: LCM: [ Start Resource ] [[WindowsFeature]DSCServiceFeature]
VERBOSE: [DSC-PULL]: LCM: [ Start Test ] [[WindowsFeature]DSCServiceFeature]
VERBOSE: [DSC-PULL]: [[WindowsFeature]DSCServiceFeature] The operation ‘Get-WindowsFeature’ started: DSC-Se
rvice
VERBOSE: [DSC-PULL]: [[WindowsFeature]DSCServiceFeature] The operation ‘Get-WindowsFeature’ succeeded: DSC-
Service
VERBOSE: [DSC-PULL]: LCM: [ End Test ] [[WindowsFeature]DSCServiceFeature] in 2.5790 seconds.
VERBOSE: [DSC-PULL]: LCM: [ Skip Set ] [[WindowsFeature]DSCServiceFeature]
VERBOSE: [DSC-PULL]: LCM: [ End Resource ] [[WindowsFeature]DSCServiceFeature]
VERBOSE: [DSC-PULL]: LCM: [ Start Resource ] [[xDSCWebService]DSCPullSRV]
VERBOSE: [DSC-PULL]: LCM: [ Start Test ] [[xDSCWebService]DSCPullSRV]
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Check Ensure
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] The Website DSCPullSRV is not present
VERBOSE: [DSC-PULL]: LCM: [ End Test ] [[xDSCWebService]DSCPullSRV] in 18.1520 seconds.
VERBOSE: [DSC-PULL]: LCM: [ Start Set ] [[xDSCWebService]DSCPullSRV]
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Check IIS Windows Authentication
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] The operation ‘Get-WindowsFeature’ started: Web-Windows-A
uth
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] The operation ‘Get-WindowsFeature’ succeeded: Web-Windows
-Auth
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Installation started…
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Prerequisite processing started…
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Prerequisite processing succeeded.
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Installation succeeded.
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Create the IIS endpoint
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Setting up endpoint at – https://DSC-PULL:8080/PSDSCPullS
erver.svc
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Verify that the certificate with the provided thumbprint
exists in CERT:\LocalMachine\MY\
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Checking IIS requirements
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Delete the App Pool if it exists
VERBOSE: [DSC-PULL]: [[xDSCWebService]DSCPullSRV] Remove the site if it already exists
VERBOSE: [DSC-PULL]: LCM: [ End Set ] [[xDSCWebService]DSCPullSRV] in 134.7100 seconds.
VERBOSE: [DSC-PULL]: LCM: [ End Resource ] [[xDSCWebService]DSCPullSRV]
VERBOSE: [DSC-PULL]: LCM: [ End Set ]
VERBOSE: [DSC-PULL]: LCM: [ End Set ] in 157.1580 seconds.
VERBOSE: Operation ‘Invoke CimMethod’ complete.
VERBOSE: Time taken for configuration job to complete is 157.336 seconds

DSCPullWEB

In the example above, I cheated a bit and installed IIS and DSC Service manually but you get the idea of what happens when you’re running the configuration. The -Wait and –Verbose handles are not needed but when you’re starting out with DSC using those handles will give you enough verbosity to see if everything is in order. When you get comfortable you can simply run the Start-DSCConfiguration without those handles and it will simply create a background job that you can pull by using Get-Job and Receive-Job cmdlets.

Now that you have a fully blown DSC Pull server up and standing, we have to set-up a registration key in order for the clients to register and authenticate to the server.

The commands above will create a GUID that will act as a registration key, and then it will copy it to the clipboard because you will need it for the LCM configuration on the target server. You can use the same registration key for all the servers, the key acts as a shared secret which servers use to authenticate.

Here’s how the LCM configuration looks like:

Set-DSCLocalConfigurationManager localhost –Path .\PullClient –Verbose
VERBOSE: Performing the operation “Start-DscConfiguration: SendMetaConfigurationApply” on target “MSFT_DSCLocalConfigurationManager”.
VERBOSE: Perform operation ‘Invoke CimMethod’ with following parameters, ”methodName’ = SendMetaConfigurationApply,’className’ = MSFT_DSCLocalConfigurationMana
ger,’namespaceName’ = root/Microsoft/Windows/DesiredStateConfiguration’.
VERBOSE: An LCM method call arrived from computer SRV-01 with user sid S-1-5-21-1972588538-2743513118-1431156491-500.
VERBOSE: [SRV-01]: LCM: [ Start Set ]
VERBOSE: [SRV-01]: LCM: [ Start Resource ] [MSFT_DSCMetaConfiguration]
VERBOSE: [SRV-01]: LCM: [ Start Set ] [MSFT_DSCMetaConfiguration]
VERBOSE: [SRV-01]: LCM: [ End Set ] [MSFT_DSCMetaConfiguration] in 0.2340 seconds.
VERBOSE: [SRV-01]: LCM: [ End Resource ] [MSFT_DSCMetaConfiguration]
VERBOSE: [SRV-01]: [] Registration of the Dsc Agent with the server https://DSC-Pull:8080/PSDSCPullServer.svc was successful.
VERBOSE: [SRV-01]: LCM: [ End Set ]
VERBOSE: [SRV-01]: LCM: [ End Set ] in 12.3750 seconds.
VERBOSE: Operation ‘Invoke CimMethod’ complete.
VERBOSE: Set-DscLocalConfigurationManager finished in 18.947 seconds.

Once you run the configuration, the DSC service will create a .meta.mof file because in this case, you are not looking to configure a server but the Local Configuration Manager. So every time you want to change the LCMs setting, you start with [DSCLocalConfigurationManager()] then you write the configuration {} block.

The LCM has three configuration modes:

ApplyOnly -> Only applies the Push/Pull configuration
ApplyAndMonitor -> Applies and monitors the Push/Pull configuration
ApplyAndAutocorrect -> Applies and corrects the Push/Pull configuration in case of a change.

As you can notice, I have set the LCM’s ConfigurationMode to ‘ApplyAndAutoCorrect’ which means that every 15 minutes, a consistency check will run and if there’s a configuration drift then it will re-apply the part of the configuration that’s been tampered with. Now this is only available for parts that are written in the configuration document. I can do as many changes as I want on the target machine as long as I don’t tamper with any of the settings that are defined in the configuration document e.g. stopping a service that’s meant to be started.

In the LCM configuration document, you can see the registration key that we previously copied to the clipboard and a ConfigurationName parameter. In PowerShell 4.0 there wasn’t a ConfigurationName parameter but a ConfigurationID which still exists for partial configurations (we will talk about it soon). For context; In PowerShell 4.0 we had to name our configuration documents to .mof which made managing configurations a nightmare and now with PowerShell V5 we can simply name then what ever we want.
Here’s an example:
V4 – 9b9f2d6d-9471-4505-9ed8-23c44e3f9980.mof
V5 – SomeConfiguration.mof

Life saver right? 🙂

Continuing on.
There’s nothing special about writing configurations that are going to end up on pull server. You don’t need to take in account node names or things like that like you would do when using the Push method. All you need to do is to produce a document that has the same name as the ConfigurationName parameter that’s configured on the targets LCM and create a checksum, which you can do by using the New-DscChecksum cmdlet. The last bit you need to do is copy the files to the Configuration folder of the pull server.
At this point you can wait 15 minutes for the LCM to kick in or you can force it by running Update-DscConfiguration -Wait -Verbose.
Here’s some output from a simple ‘Stop The BITS service’ configuration:

DSCConfig

PS C:\> Update-DscConfiguration -Wait -Verbose
VERBOSE: Perform operation ‘Invoke CimMethod’ with following parameters, ”methodName’ = PerformRequiredConfigurationChecks,’className’ = MSFT_DSCLocalConfigura
tionManager,’namespaceName’ = root/Microsoft/Windows/DesiredStateConfiguration’.
VERBOSE: An LCM method call arrived from computer SRV-01 with user sid S-1-5-21-1972588538-2743513118-1431156491-500.
VERBOSE: [SRV-01]: [] Executing Get-Action with configuration ‘s checksum: .
VERBOSE: [SRV-01]: [] Executing Get-Action with configuration ‘s checksum returned result status: GetConfiguration.
VERBOSE: [SRV-01]: [] Checksum is different. LCM will execute GetConfiguration to pull configuration .
VERBOSE: [SRV-01]: [] Executing GetConfiguration succeeded. Configuration was pulled from server.
VERBOSE: [SRV-01]: [] Applying the new configuration(s) pulled.
VERBOSE: [SRV-01]: LCM: [ Start Resource ] [[Service]bitsservice]
VERBOSE: [SRV-01]: LCM: [ Start Test ] [[Service]bitsservice]
VERBOSE: [SRV-01]: LCM: [ End Test ] [[Service]bitsservice] in 2.3570 seconds.
VERBOSE: [SRV-01]: LCM: [ Start Set ] [[Service]bitsservice]
VERBOSE: [SRV-01]: [[Service]bitsservice] Service ‘bits’ already exists. Write properties such as Status, DisplayName, Description, D
ependencies will be ignored for existing services.
VERBOSE: [SRV-01]: [[Service]bitsservice] Service ‘bits’ stopped.
VERBOSE: [SRV-01]: LCM: [ End Set ] [[Service]bitsservice] in 0.6250 seconds.
VERBOSE: [SRV-01]: LCM: [ End Resource ] [[Service]bitsservice]
VERBOSE: Operation ‘Invoke CimMethod’ complete.
VERBOSE: Time taken for configuration job to complete is 7.339 seconds

OK. We’ve learned how to configure DSC Web Pull servers and make a client-server to pull the configuration we’ve produced. There’s one last thing I want to cover before ending this post and that’s Partial Configurations.

At the start of this post I talked having multiple configuration files that can serve as a baseline and specialization documents. This can even expanded even more as you can have multiple teams working on their separate configuration files and you just configure the LCM to pull them together. By using this method you basically avoid having a single file with 1000 or more lines. This is not the single method of splitting configurations, there’s the method of nesting with composite resources but you need to create separate module folders for that to work, and I’m not going to cover it in this already long article 🙂

In order to use partial configurations you need to adapt the LCM config file a bit and start using ConfigurationIDs because ConfigurationNames are not supported in this way. Remember the part with PowerShell V4? It’s not quite like that.
Here’s how you configure the LCM for Partial Configurations:

In the example above I listed only two partial configurations but if you want, you can have multiple partial configurations that can be pulled from multiple DSC pull servers.

As you can see the main difference is that you declare each configuration as a PartialConfiguration which in my case they are named Base and Extra and instead of having a ConfigurationnName declared I have a ConfigurationID with a GUID as a value which I will be using in the naming scheme of the checksum and mof files like this:

Base.a6546088-c6d0-4c8e-ad12-2723a6b1c2cd.mof
Base.a6546088-c6d0-4c8e-ad12-2723a6b1c2cd.mof.checksum

Extra.a6546088-c6d0-4c8e-ad12-2723a6b1c2cd.mof
Extra.a6546088-c6d0-4c8e-ad12-2723a6b1c2cd.mof.checksum

See the difference? Instead of .mof, there’s ..mof.

Now once you’ve done that. Run the Update-DscConfiguration -Wait -Verbose cmdlet and check the output:

Update-DscConfiguration -Wait -Verbose

VERBOSE: Performing the operation “Start-DscConfiguration: SendMetaConfigurationApply” on target “MSFT_DSCLocalConfigurationManager”.
VERBOSE: Perform operation ‘Invoke CimMethod’ with following parameters, ”methodName’ = SendMetaConfigurationApply,’className’ = MSFT_DSCLocalConfigurationManager,’namespaceName’ =
root/Microsoft/Windows/DesiredStateConfiguration’.
VERBOSE: An LCM method call arrived from computer SRV-01 with user sid S-1-5-21-1972588538-2743513118-1431156491-500.
VERBOSE: [SRV-01]: LCM: [ Start Set ]
VERBOSE: [SRV-01]: LCM: [ Start Resource ] [MSFT_DSCMetaConfiguration]
VERBOSE: [SRV-01]: LCM: [ Start Set ] [MSFT_DSCMetaConfiguration]
VERBOSE: [SRV-01]: LCM: [ End Set ] [MSFT_DSCMetaConfiguration] in 0.0620 seconds.
VERBOSE: [SRV-01]: LCM: [ End Resource ] [MSFT_DSCMetaConfiguration]
VERBOSE: [SRV-01]: LCM: [ End Set ]
VERBOSE: [SRV-01]: LCM: [ End Set ] in 0.1100 seconds.
VERBOSE: Operation ‘Invoke CimMethod’ complete.
VERBOSE: Set-DscLocalConfigurationManager finished in 3.312 seconds.
VERBOSE: Perform operation ‘Invoke CimMethod’ with following parameters, ”methodName’ = PerformRequiredConfigurationChecks,’className’ = MSFT_DSCLocalConfigurationManager,’namespace
Name’ = root/Microsoft/Windows/DesiredStateConfiguration’.
VERBOSE: An LCM method call arrived from computer SRV-01 with user sid S-1-5-21-1972588538-2743513118-1431156491-500.
VERBOSE: [SRV-01]: [] Executing Get-Action with configuration Base’s checksum: E35DB1051B3C3CADA1A0D8F304FE21126E2C5A967B0FE9FD97663D21D5B55C02.
VERBOSE: [SRV-01]: [] Executing Get-Action with configuration Base’s checksum returned result status: Ok.
VERBOSE: [SRV-01]: [] Updated configuration not found on pull server so no action taken. Ensure that a configuration with a different checksum exists on th
e pull server for target node.
VERBOSE: [SRV-01]: [] Executing Get-Action with configuration Extra’s checksum: F92BF7133BA0473A43A5749139E92852FA64FFDC1C008DD5581CDD8860147197.
VERBOSE: [SRV-01]: [] Executing Get-Action with configuration Extra’s checksum returned result status: Ok.
VERBOSE: [SRV-01]: [] Updated configuration not found on pull server so no action taken. Ensure that a configuration with a different checksum exists on th
e pull server for target node.
VERBOSE: Operation ‘Invoke CimMethod’ complete.
VERBOSE: Time taken for configuration job to complete is 0.949 seconds

That’s all folks! Zero to Full DSC laziness. 🙂

I know this was a long article but I wanted to cover almost all the scenarios regarding this little nugget. Now for production deployments you need to have a more advanced configuration like modifying the registry in order to block IIS for using unsecured protocols, request certificates from the CA server, stopping the default web site, set up the necessary firewall rules and so on. DSC can be hard to start with once it’s in place, but once configuring and managing server configurations will be a breeze.

That’s it. Have a good one!

Pin It on Pinterest