PowerShell; WSUS 2016 – 2012 server-side vs. client-side targeting and how to automate grouping.

Every admin or engineer who has installed a Windows Server Update Services server (WSUS) on their network has had to choose between sever-side and client-side targeting. The choice between flexibility and automation can often be a difficult one to make. Maybe it doesn’t have to be? PowerShell allows us to access the internal workings of WSUS and customise them to our liking. Read-on to see the method I came up with for allowing the flexibility of server-side targeting with automated group assignment.

For those who are unfamiliar with WSUS targeting options, server-side targeting allows an administrator to add or remove systems to or from WSUS groups in the software’s management console. Many of the companies I have worked for like to periodically change-up their patching routines. This usually means modifying your update groups. For example; perhaps all the SQL servers are currently grouped / patched together but the new Director wants them patched with the applications that use their databases. These types of changes occur in real-time and are simple to manage in the GUI when you’re set up for server-side targeting. The drawback to this option is that someone has to sort all of the computers into the correct groups manually; if your network has a lot of nodes, the task can be daunting. Furthermore, admins will need to watch for the addition of new systems and sort those into the proper groups.

The other option is client-side targeting. In this configuration, you create GPOs that tell each OU they are linked to, what group those servers belong in. This automates the sorting process but is much less flexible. In the example above, to regroup our SQL servers we would need to create new GPOs for the OUs that contain them and remove the old ones. Then we’d need to wait for all the replication and registration to occur which can take a very long time on large networks.

With a little PowerShell know how, we can close the gap between the server-side setup that most admins would prefer to run (who doesn’t like flexibility) and the client-side config you almost feel forced to run on a large network. WSUS has had a dedicated PowerShell interface since the 2012 edition. You can use PowerShell on the older versions, but you need to manually load the assemblies and the command structure is slightly different (Google it).

First, if you haven’t already, you’ll need to install the RSTAT tools for your operating system. You’ll also want to install the SQL Server 2012 CLR Types and SQL Server Report Viewer runtime. The RSTAT tools will add the PowerShell module for WSUS to your system and the other pieces will let you run WSUS reports if you need them.

For WSUS to see your systems at all, you’ll need to point each server’s Windows Update service at your WSUS server. The easiest way to do this is with a GPO linked to the top-level server and/or workstation OU(s) in your domain. You’ll need to configure the Specify intranet Microsoft update service location and the Configure Automatic Updates policies.

DO NOT CONFIGURE the Enable Client Side Targeting policy.

Your WSUS server should be configured for server-side targeting. If you don’t do this, the options for moving computers to new groups will not be available in the management console at all. The setting is in the WSUS managment console.

If everything has worked out, all of the systems that we’re going to manage patching on will now be in the “Unassigned Computers” group. This is exactly where we need them be. Having them in this group means that our script can be much simpler. We won’t have to check for connectivity, SSL, RPC, and all that jazz because the systems wouldn’t show up in the “Unassigned Computers” group if that stuff wasn’t working. In fact, if you have systems that didn’t show up, you need to start checking those protocols and settings. You’ll also want to be sure that you didn’t miss an OU with the GPO that is configuring the update services to point at your WSUS server. If you opted to encrypt the traffic to and from WSUS, you’ll also want to make sure you CA and Root certs are trusted by the client systems.

Now you’ll need to configure all your Target Groups in WSUS. Until you get the hang of how this technique works, I suggest that you create a group for each of the system OUs in your Active Directory. This makes sorting easier to implemeant and explain. Once you understand how everything works, you’ll have no problem customizing things. It is important to keep in mind that because we’re using server-side targeting, computers can belong to more than one patching group, this will not cause any kind of conflict. WSUS only patches a computer once with any given patch so whichever group applies the update first wins.

Before proceeding, you’ll need to import the ActiveDirectory and WindowsUpdate PowerShell Modules (see the first two lines below). There are lots of ways to access WSUS through PowerShell (this is Windows after all) but one of the easiet is to call the connection every time that you want to use it. We can use this code to build a list of the computers in our Unassigend Group. Make sure you adjust the portnumber parameter to match your situation. The code below is referencing the default encrypted port for the manangment console.

#Import the modules we need:
Import-Module ActiveDirectory
Import-Module WindowsUpdate
#Build a list of the unassigned computers names:
$NewServersFull = Get-WsusServer
-Name WSUS_Server_Name -PortNumber 8530|
Get-WsusComputer -ComputerTargetGroups "Unassigned Computers"|
select Fulldomainname -ExpandProperty Fulldomainname

Notice that we assigned that list of computer names to a variable? We’re going to run these computers through the Get-ADComputer cmdlet to see if it belongs to a particular OU. The Get-ADComputer cmdlet tends not to like FQDNs as an identity parameter so we need to shorten our names to just the NETBIOS portion (strip off the domain name).

$NewServers = Foreach ($server in $newserversfull) {
$server.split(‘.’)[0]
}

Now $NewServers is an array containing our short server names. This list can be used as the identity parameter in a Get-ADComputer loop. That loop is going to check to see if a computer belongs in a given OU. I like to create functions for each system OU in my Active Directory and then loop the list of names through each. When a system matches the OU I’m coding for, I insert it into the correct WSUS target group. Here’s what one of those functions looks like.

Function MY-OU-NAME {
$MY_OU_NAME = Foreach ($server in $newservers) {
Get-ADComputer -Identity $server -Properties * |
Select dnshostname,canonicalname -ExpandProperty
canonicalname| Where canonicalname -Like
"mydomain.com/mydomainsite/ToplevelOU/Servers/*"|
Select dnshostname -ExpandProperty dnshostname
}

Foreach ($server in $MY_OU_NAME) {
Get-WsusServer -Name WSUSSERVERNAME -PortNumber 8530|
Get-WsusComputer -NameIncludes $server|
Add-WsusComputer -TargetGroupName "MY - WSUS - GROUP"
}
}

The * on the end of the canonicalname is important, it allows the where statement match every system in that location. You could also use the filter and searchbase parameters to search the OU directly, instead of the canonicalname. I don’t because I had already generated a list of canonicalnames for all my OUs for another project and I’m lazy 🙂 . If you want to find the canonicalname for an OU, just pick a computer in the OU and run Get-ADComputer -Identity computername -Properties *|select CanonicalName or use ADUC.

Copy and paste a new function into your script for every OU that has computers you want to assign to a WSUS group. For each (man I type that a lot) function, you’ll need to change the Function Name (MY-OU-NAME), Variable Name (MY_OU_NAME), and the WSUS target group name (“MY – WSUS – GROUP”).

At the end of our script we can use a little logic to prevent the process from running if there aren’t any new computers in the unassiged group. We can also send a report showing the servers that were added. Or, we can notify someone that the script ran but there weren’t any new servers to add.

If ($newserversfull.count -gt 0 ) {
$body = $newserversfull|out-string
FunctionName
FunctionName
FunctionName
Send-MailMessage -SmtpServer my.email.server
-From report@wsus.mydomain.com
-to my-email@mydomain.com
-Subject "WSUS Servers Added"
-body $body
}
Else {
Send-MailMessage -SmtpServer my.email.server
-From report@wsus.mydomain.com
-to my-email@mydomain.com
-Subject "WSUS No New Servers this time -EOM"
}
$leftovers = Get-WsusServer -Name WSUS_Server_Name -PortNumber 8530|
Get-WsusComputer -ComputerTargetGroups "Unassigned Computers"|
select Fulldomainname -ExpandProperty Fulldomainname
If ($leftovers.count -gt 0) {
Send-MailMessage -SmtpServer my.email.server
-From report@wsus.mydomain.com
-to my-email@mydomain.com
-Subject "Systems that coudn't be grouped by WSUS"
-body $leftovers
}

That last little bit ($leftovers) runs the same code we started with. If our script has done its job, there shouldn’t be anything left in the unassigned computers group. If there are computers still in there, you’ll want to know so that you can manually intervene.

All that’s left is to schedule the script with task manager to run automatically with credentials that have enough permissions to manage WSUS. I set mine up to run twice a day; just create a new scheduled task and in the action set the comand to “powershell.exe” and in the arguments put “the\file\path\to\myscript.ps1” and set the trigger to your desired frequency. When you save the task it will prompt you for the credentials it should run with (be sure to check the box to run whether a user is logged in or not).

I call my little piece of magic “The_Sorting_Hat.ps1” (yes, I’m a Harry Potter fan). Its been a life saver. When I need to move a computer to a new group, I just launch the WSUS console and put it there. Since the system isn’t in the unassigned computers group the script has no effect on it. I can manually create new groups for adhoc needs and add systems to multiple groups, all while not worrying about new systems hanging around without being patched.

1 Comment

Leave a comment