System Center 2012 R2 Configuration Manager does a great job of deploying Windows operating systems. We (1E) have been able to hit some pretty high success rates in helping our customers with their Windows migrations. However, if not done correctly, OSD can be very dangerous and can cripple your environment in a short amount of time. Take Emory University for an example – a simple mistake was made and a Windows deployment was sent out to all laptops, desktops and servers! With the correct precautions in place, this risk can be easily minimized or even eliminated.
There are several checks and balances that can be put into place in order to prevent something like this from happening and in this post I will focus on Maintenance Windows and limiting Collections. If you are still stuck in the habit of setting up deployments to All Systems, then the best thing you can do is break that bad habit now! Otherwise, be sure to keep a copy of your resume updated in case something really bad happens.
The first thing that should be done is to create two root level collections – one for All Workstations and one for All Servers. Both of these will be limited to the All Systems collection. Also, you should limit the number of collections that are limited to the All Systems collection for performance reasons, but this goes beyond the intent of this blog post. If possible, all other collections should be limited to either the All Workstations or All Servers. By limiting an OS Deployment collection to just the All Workstations, you automatically eliminate the possibility of servers being accidentally targeted (as what happened with Emory University). Both of these collections only need to be updated once a week and can be enabled for incremental updates. Each collection will have a query based membership rule that is configured for the System Resource > Operating System Name and Version property.
The last (and most important) thing that needs to be done is an OSD Maintenance Window needs to be configured on each collection. The key is to make this window in the past. Please keep in mind that this method is not fool proof, as I will explain below. Just like wearing a seat belt in a car – it doesn’t prevent you from getting in an accident, but it will minimize the chances of getting hurt. So, the intention is to minimize the risk, just like we did by splitting up servers and workstations into two different collections. By creating a window in the past, you will prevent any future OS Deployments from running (provided they were configured with the defaults). Even if someone accidentally sent the Required OS Deployment to All Workstations, with a maintenance window set in the past, all clients would start returning the following status message:
Message ID: 10074
The program for deployment “AZ1476C5” failed (“AZ105DA7” – “*”). There is no maintenance window with a duration at least as large as the program’s defined maximum runtime. Consequently, the program may never run on the client.
Hopefully, someone monitoring the deployment will see a flood of these status messages and realize that hundreds, if not thousands of systems were about to be re-imaged and correct the targeting collection membership.
When configuring a Required Deployment, the Software Installation and System Restart behavior as it pertains to maintenance windows is unchecked by default. In other words, someone would have to make a decision to enabled both of these boxes, which would render the above fail-safe solution useless. In the next part, I will talk about other methods that can be combined with this one in order to further minimize the risk of a OSDisaster.
Below is a PowerShell script that will create the collections, schedules and maintenance windows that I talked about above. This uses newer cmdlets that are available starting in System Center 2012 R2 Configuration Manager. As always, test in a lab environment first!
#Create Root Collections with OSD MWs #Author: Mike Terrill #Version 1.0 #Disclaimer: #Your use of these example scripts or cmdlets is at your sole risk. This information is provided “as-is”, without any warranty, whether express or implied, of accuracy, #completeness, fitness for a particular purpose, title or non-infringement. I shall not be liable for any damages you may sustain by using these examples, whether direct, #indirect, special, incidental or consequential. #Set the collection evaluation schedules $AllWorkstationsSchedule = New-CMSchedule -Start "1/1/2014 12:00 AM" -DayOfWeek Saturday -RecurCount 1 $AllServersSchedule = New-CMSchedule -Start "1/1/2014 12:00 AM" -DayOfWeek Sunday -RecurCount 1 #Create the All Workstations collection $AllWorkstations = New-CMDeviceCollection -Name "All Workstations" -LimitingCollectionName "All Systems" ` -RefreshSchedule $AllWorkstationsSchedule -RefreshType Both #Create the All Servers collection $AllServers = New-CMDeviceCollection -Name "All Servers" -LimitingCollectionName "All Systems" ` -RefreshSchedule $AllServersSchedule -RefreshType Both #Create the All Workstations query membership rule Add-CMDeviceCollectionQueryMembershipRule -CollectionName "All Workstations" -QueryExpression ` "select * from SMS_R_System where SMS_R_System.OperatingSystemNameandVersion like '%Workstation%'" -RuleName "All Workstations" #Create the All Servers query membership rule Add-CMDeviceCollectionQueryMembershipRule -CollectionName "All Servers" -QueryExpression ` "select * from SMS_R_System where SMS_R_System.OperatingSystemNameandVersion like '%Server%'" -RuleName "All Servers" #Create a 5 min schedule in the past $MWSchedule = New-CMSchedule -Start "1/1/2014 12:00 AM" -DurationInterval Minutes -DurationCount 5 -Nonrecurring #Create a restrictive OSD MW that occured in the past New-CMMaintenanceWindow -CollectionID $AllWorkstations.CollectionID -ApplyToTaskSequenceOnly -Name "Restrict OSD" -Schedule $MWSchedule New-CMMaintenanceWindow -CollectionID $AllServers.CollectionID -ApplyToTaskSequenceOnly -Name "Restrict OSD" -Schedule $MWSchedule
Originally posted on https://miketerrill.net/
Hi!
I actually thought of doing this but then it hit me, how do I add new computer to the OSD collection? That computer won’t have any software inventory hence cannot be a member of “All Workstations” collection? Right?
Typically you would create a separate Collection and Deployment for new computers. However, if you did want to add them into the All Workstations Collection, there are a couple of things that could make this work. First, you could simply add an ‘or’ to the query rule and base it off of the System Resource-Agent Name where it is equal to Manual Machine Entry. But if you also provision servers, this might not be your best bet. Another method would be to add the OS property to the DDR for the imported object – the System Resource class comes from the DDR and not hardware or software inventory. But the best approach is to split out the new computers from the refresh (existing) computers for OS deployments. There are some nice options on Deployments that make it so they are only available to new computers. The key thing is how deployments are targeted (Required vs. Available) and what is targeted. Required is always the one with the most risk and should be handled with the most care.
Excellent and timely post!
Dumb question but since your applying a maintenance window to All Workstations for Task Sequences wouldn’t this stop ALL task sequences……for instance, if you want to reimage an existing machine due to a virus?
It depends on your strategy. If the system was still able to get Available Deployments, then the user or tech could run the job at will. But for Required Deployments, the system would need to be in a collection with a proper maintenance window or it would need to be built via bare metal. In the follow parts of this series, I plan on outlining a strategy that can be used as an example.
Pingback: 10 #1 best practices for OS Deployment with ConfigMgr 2012 R2 | Greg's Systems Management Blog