Using PowerShell DSC to deploy update packages

Introduction

Administrators of Windows Server-based networks often employ scripted solutions for automating complex tasks that would require a series of carefully performed tedious steps in order to successfully customize and manage different aspects of their environment. One powerful new tool in the administrator’s toolbox for accomplishing this is Windows PowerShell Desired State Configuration (DSC), a new management platform first introduced in Windows PowerShell 4.0 that facilitates deploying and managing configuration data for services as well as managing the environment where such services run. To help our readers understand some of the power available for them in DSC, I’ve asked fellow Microsoft MVP Desmond Leeto show in detail how one might use DSC to simplify and automate the task of pushing out .msu update packages in a Windows environment. Desmond specializes in end-to-end enterprise infrastructure and innovative cloud solutions built around proven business processes, effective project team management and people integration across various industries worldwide. He has been recognized as a Microsoft Most Valuable Professional (MVP Skype for Business) for his dedicated passion and long term volunteer work in the IT community. Desmond holds a MSc. from University College London (UCL) and is a SVEB certified trainer, coach and founder of the Swiss IT Pro User Group (www.swissitpro.ch), an independent, non-profit organization for IT Pros by IT Pros championing Microsoft and related technologies. Desmond is also an established author and speaker at major international and regional events known for his real-world insights with over 2 decades of hands-on experience, and contributes frequently to several highly rated publications and engages as a moderator in popular Microsoft public forums/newsgroups. You can follow his IT adventures at www.leedesmond.com.

Scenario

Desired State Configuration (DSC) was first introduced in PowerShell 4.0 and is the version shipped in-the-box in both Windows 8.1 and Windows Server 2012 R2. This standards based system management platform opens up a whole new world of opportunities in the administration of heterogeneous platforms from Linux to workgroup and Active Directory domain environments.

Imagine for a moment that you are the system administrator and intend to upgrade to PowerShell 5.0 by way of installing the Windows Management Framework 5.0 RTM (re-released on 24 Feb 2016). A typical approach is the manual download and “click-to-install” of the WMF5 executable which is delivered in the form of an .msu update package. Files with such name extensions are associated with the Windows Update Standalone Installer (wusa.exe) located in the %windir%\System32 folder.

For administrators who need to maintain several servers in the organization, Windows Server Update Services (WSUS), Intune or third party solutions may have already been deployed. These methods to rollout patches, hotfixes and updates rely on the availability of the right infrastructure besides licensing considerations. They are tried and tested and will continue to serve their purpose well into the foreseeable future.

An alternative approach is to exploit DSC to achieve similar goals whether it is a low-budget, simple lab setup or large-scale enterprise deployment. Think of DSC as a free “make-it-so” agent that is delivered as part of PowerShell in every supported version of Windows. The magic is performed by what is termed as a Resource (the “doer”) where a number of commonly used features or scenarios are provided in the PSDesiredStateConfiguration module. DSC will automatically enforce compliance on target machine nodes and maintain idempotent should deviation be detected from the norm. Desired state configuration settings can be deployed by means of the Pull or Push mechanism. As the latter is more involved with additional hard- and software requirements, our focus in this article will concentrate on using the simpler Push scheme.

Solution

Let us start by inspecting the local DSC resources with the help of Get-DscResource. From the given output, you found out that your endeavor to install WMF5 cannot be met with any of the in-the-box resources. Turning your attention to Find-DscResource, it was discovered that the xMicrosoftUpdate resource in the xWindowsUpdate module, obtainable as part of the PowerShell Gallery PSGallery repository, does fulfill our objectives here.

Next, you can elect to download, save or directly install the xMicrosoftUpdate module on your source administrative workstation using Install-Module. You are now almost ready to start writing the initial declarative configuration DSC block in PowerShell.

But wait! How do you get the .msu package, say from an internal web server or SMB network file share, to the destination nodes? Additionally, the xHotfix DSC resource (within the xMicrosoftUpdate module) is obligatory to perform the actual patch update and is unlikely to be present at the remote machines either. Your company adopts industry best practice where servers do not have direct internet access hence this web download method is ruled out.

You noticed that the local File DSC resource is a possible candidate for this assignment. Recall that DSC runs under the context of the LOCAL SYSTEM account with no possibility of network access outside the boundaries of the host itself. One workaround to this security constraint is to painstakingly grant access permissions on the file share housing the .msu and xMicrosoftUpdate module to all the remote computer accounts (target DSC nodes). This tactic is described in “Copying PowerShell modules and custom DSC resources using DSC”.

A much easier approach to transfer the needed files across the wire is to make use of the flexible Script DSC resource as shown in Figure 1.

Image
Figure 1

As you can see, the code is pretty straightforward and self-explanatory with the actual file copy carried out on Lines 44-45 of Figure 1. Nevertheless, you will need to setup the correct credentials and pass it to New-PSDrive in the event that the network file share is access protected. You can potentially skip the drive mapping and perform the copy operation directly with the UNC path of the network file share. This is provided that the latter permits anonymous access or the participating machines are part of an Active Directory domain network with appropriate access rights.

Note that the files that make up the xWindowsUpdate module are copied straight to the path defined by the $pathtargetModule variable. Automatic module discovery and loading will happen as long as they are placed into this or one of the other folders as defined in $env:PSModulePath.

Evidently, saving the user name and password as plain text is one major disadvantage here. Further, you may also have to handle possible errors arising out of the unavailability of the arbitrarily selected network drive letter. To mitigate this, consider running Get-WmiObject to enumerate the drive types and associated letters that are already in use.

At this juncture, all you need to do is to pack everything together within the declarative Configuration code block to arrive at Figure 2 (Step 1):

Image
Figure 2

To generate the Managed Object Format (.mof) text file, simply call DscWMF5CopyFiles (the name of the Configuration block) with parameters as needed. Note that a Configuration block behaves exactly like a regular function.

##### STEP 2       #####

##### Generate MOF #####

 

$Computername = “169.254.64.139”

 

DscWMF5CopyFiles `

-Computername $Computername `

       -OutputPath C:\dsc\DscWMF5CopyFiles

Assuming that the pre-requisites on the remote DSC target are fulfilled, namely PowerShell remoting and .NET Framework 4.5 or higher, you are now in the position to push out the configuration settings by executing the following:

##### STEP 3                 #####

##### Push out configuration #####

 

Start-DscConfiguration `

                -Path “C:\dsc\DscWMF5CopyFiles” `

                -ComputerName $Computername `

                -Verbose -Wait `

                -Credential (Get-Credential)

In a workgroup environment, be aware that using the -Credential parameter may be a necessity due to disparate security access profiles on the destination machines.

Note:
Prior to pushing out the configuration, you must remove the following entries from the .mof if the file is generated on a machine running PowerShell 5.0 or Windows Management Framework 5.0 targeting an older PowerShell / WMF installation in order to avoid runtime (in)compatibility errors:

ConfigurationName = “DscWMF5rtm”;

MinimumCompatibleVersion = “1.0.0”;

CompatibleVersionAdditionalProperties={“Omi_BaseResource:ConfigurationName”};

Name=” DscWMF5rtm”;

Now, with the successful transfer of the needed files to the target nodes through DscWMF5CopyFiles, the succeeding step is to prepare a separate DSC Configuration block to describe the actual desired settings of having (and keeping) WMF5 deployed as illustrated in Figure 3:

Image
Figure 3

We can then go ahead to generate the MOF file (Step 2) before instructing PowerShell to initiate the actual WMF5 deployment (Step 3). In order for DSC to enforce the stated configuration, these scripts must be deployed together; Listing 1 shown in the next section below helps setup the dependencies (.msu and xWindowsUpdate module) while Listing 2 dictates the implementation details. Re-running these steps are only required if new machines come into operations, servers get decommissioned or the path to the network file share is updated, for instance.

Notes:
You may be wondering why the xHotfix and Script blocks are not  packed together in a same Configuration block like DscWMF5Rollout or DscWMF5CopyFiles. Unless the destination nodes already have the xWindowsUpdate module installed, an error message will be generated when Start-DscConfiguration is executed:

The PowerShell provider xWindowsUpdate does not exist at the PowerShell module path nor is it registered as a WMI provider.

    + CategoryInfo          : InvalidOperation: (root/Microsoft/…gurationManager:String) [], CimException

    + FullyQualifiedErrorId : ModuleNameNotFound

    + PSComputerName        : 169.254.64.139

Therefore, keeping the xHotfix and Script code sections in distinct Configuration blocks is essential to ensure that dependencies can be maintained yet separately managed.

In addition, although certain patches and hotfixes demand a machine reboot in order to complete installation, it is a good thing that pushing updates over DSC does not just trigger an automatic restart without administrative intervention. By default, the Local Configuration Manager (LCM, literally the “make-it-so” agent) is set to false against RebootNodeIfNeeded. With caution, you can overwrite this behavior through Set-DscLocalConfigurationManager over a remote CIM session.

Listing 1

#requires -version 4.0

 

##### STEP 1                   #####

##### Author MOF (Declarative) #####

Configuration DscWMF5CopyFiles

{

    param (

        [string[]]$Computername = “localhost”

    )

    Import-DscResource -ModuleName ‘PSDesiredStateConfiguration’

 

    Node $Computername

    {

       Script DscWMF5SourceFiles {

            GetScript = {

                @{ Result = Test-Path -Path “$env:ProgramFiles\WindowsPowerShell\Modules\xWindowsUpdate” }

            } #GetScript

 

            SetScript = {

                param (

                    [string[]]$Computername = “localhost”

                )              

                $pathtarget = “c:\source”

                $pathtargetModule = “$env:ProgramFiles\WindowsPowerShell\Modules”

                $hosttarget = “169.254.64.139”

 

                $pathsource = “\\169.254.60.85\share”

                $filesourceDrive = “Z”

               

                $username =”administrator”

                $password = “………”  #file share

                $spassword = $password | ConvertTo-SecureString -Force -AsPlainText

 

                $cred = New-Object -typename System.Management.Automation.PSCredential `

                            -argumentlist $username, $spassword

               

                #map a network drive to common SMB file share

                New-PSDrive -Name $filesourceDrive -PSProvider FileSystem `

                            -Root $pathsource -Credential $cred

 

                if (-not (Test-Path $pathtarget) ) { mkdir $pathtarget }

 

                #transfer files to destination DSC nodes

                Copy-Item “$($filesourceDrive):\Win8.1AndW2K12R2-KB3134758-x64.msu” $pathtarget

                Copy-Item “$($filesourceDrive):\xWindowsUpdate” $pathtargetModule -recurse

 

                Remove-PSDrive $filesourceDrive

            } #SetScript

 

            TestScript = {

                Test-Path -Path “$env:ProgramFiles\WindowsPowerShell\Modules\xWindowsUpdate”

            } #TestScript

        } #Script DscWMF5SourceFiles

 

   }     #Node $Computername

 

}        #Configuration DscWMF5CopyFiles

 

 

 

##### STEP 2       #####

##### Generate MOF #####

$Computername = “169.254.64.139”

 

DscWMF5CopyFiles -Computername $Computername `

           -OutputPath C:\dsc\DscWMF5CopyFiles

 

 

 

##### STEP 3                 #####

##### Push out configuration #####

Start-DscConfiguration `

                -Path “C:\dsc\DscWMF5CopyFiles”  `

                -ComputerName $Computername `

                -Verbose -Wait `

                -Credential (Get-Credential)

 

Listing 2

#requires -version 4.0

 

##### STEP 1                   #####

##### Author MOF (Declarative) #####

Configuration DscWMF5Rollout

{

    param (

        [string[]]$Computername = “localhost”

    )

    Import-DscResource -ModuleName ‘PSDesiredStateConfiguration’,

                                   ‘xWindowsUpdate’

 

    Node $Computername

    {

        xHotfix HotfixInstall

        {

            Path = ‘c:\source\Win8.1AndW2K12R2-KB3134758-x64.msu’

            Id = ‘KB3134758’

            Ensure = ‘Present’

        } #xHotfix HotfixInstall

 

   }     #Node $Computername

 

}        #Configuration DscWMF5Rollout

 

 

 

##### STEP 2       #####

##### Generate MOF #####

$Computername = “169.254.64.139”

 

DscWMF5Rollout -Computername $Computername `

           -OutputPath C:\dsc\DscWMF5Rollout

 

 

 

##### STEP 3                 #####

##### Push out configuration #####

Start-DscConfiguration `

                -Path “C:\dsc\DscWMF5Rollout”  `

                -ComputerName $Computername `

                -Verbose -Wait `

                -Credential (Get-Credential)

Conclusion

In this article, you learnt how simple it is to push out .msu update packages through the use of the Script and xWindowsUpdate DSC resources without complicated, time-consuming setup or costly investments. Once successfully deployed, it is the LCM’s ongoing duty to maintain “status-quo” on the remote DSC targets without further involvement of the administrator. Using the sample declarative Configuration code blocks as a starting point, you should be confident to assemble the needed pieces together to effectively deploy updates and keep your machines standardized.

1 thought on “Using PowerShell DSC to deploy update packages”

  1. This was exactly the help I was looking for. Good post.

    One change I had to make was when upgrading from version 4 to 5. When I downloaded the xWindowsUpdate package, it contained a sub folder 2.5.0.0 and then the package files. What I found is V4 doesn’t support versioning this way and I had to move the files from the 2.5.0.0 sub folder up to the main xWindowsUpdate folder and then everything worked.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top