Dynamic Patch Maintenance Windows Using a Single Action

by | Aug 26, 2019 | BigFix Tips & Tricks | 0 comments

1Patching using BigFix is easy.  Whether you’re sending off a single patch or a hundred wrapped in a Baseline, you use the same set of clicks.  The learning curve is more like a learning ‘ramp’.  Once you know how to patch Windows computers you know how to patch Linux, MacOS, A I X, etc.  The bigger challenges in any corporate environment are patching the exact set of systems on exactly the right date and for exactly the right amount of time.  This is where Maintenance Windows come in. 

BigFix has a Maintenance Window feature which once set up will automatically unlock computers for just a specific time-frame (the pre-defined maintenance window) and then lock them again when the time expires. It is during this time that your patch actions can be processed by those computers. But the difficulties I see with using maintenance windows are in the amount of front-end work that needs to be done to set them up and how rigid they are once setup:

  1. Clients have to be locked so they do not receive the patch action during any time outside the defined maintenance window.
  2. You must create a maintenance window and then “take action” to deploy it to clients
  3. You must enable the ability of clients to be unlocked during this maintenance window by deploying the task “Enforce Maintenance Window with Client Locking”
  4. After the Maintenance Window is created and distributed to Clients you must still deploy the baseline that contains your patches.

The complexity of this process becomes all the more apparent if you have different groups of computers that have their own Patch Day/Time and week of the month. You have to create individual windows for each of those time-frames and then deploy them to each computer group that needs to be patched during that window. Additionally, once created and deployed to the endpoints you have no way to edit the date or time values of the window except by going into the action script of the resulting task, modifying the desired parameters and re-deploying the task. Lastly, even when you edit the task this way your updates will not be reflected in the maintenance window dashboard. Anyone looking at the dashboard will still think the maintenance window is set to the original values with which it was created. I have a better way.

The Execution parameters tab of every ‘Take Action’ dialog box gives you a set of ‘Constraints’ that can be used to control how that action is interpreted by a client. If you were only ever dealing with one maintenance window then you could use the built-in time and day-of-the-week constraints to limit when the action can be executed by clients; however, when you have multiple patching windows it becomes more difficult to accomplish your patching with just a single action. The way I got around this limitation was by using the “Run only when” constraint.

I started by creating a property called “Patch Window Open” which evaluates to ‘True’ when the client’s clock indicates that it is in the patch window and ‘False’ when it isn’t. Selecting that property in the “Run only when” constraint allows you to use a single action targeted to all endpoints that will execute only when the value of the property is ‘True’.

The secret sauce here is the pre-requisite client settings that must be configured and the relevance of the “Patch Window Open” property.

First you must ‘tag’ your clients with specific settings:

  • Patch Week
  • Patch Day
  • Patch Start Time
  • Patch End Time

This can be accomplished individually or en masse to all the systems that share a specific patch window.  Once done this never has to be touched again unless you wish to change a client’s patch window.  Next you create the property and insert the following relevance:

if (if current date < (first sunday of current month_and_year) then "0" else if current date >= (first sunday of current month_and_year) and current date < ((first sunday of current month_and_year) + (7*day)) then "1" else if current date >= ((first sunday of current month_and_year) + (7*day)) and current date < ((first sunday of current month_and_year) + (14*day)) then "2" else if current date >= ((first sunday of current month_and_year) + (14*day)) and current date < ((first sunday of current month_and_year) + (21*day)) then "3" else if current date >= ((first sunday of current month_and_year) + (21*day)) and current date < ((first sunday of current month_and_year) + (28*day)) then "4" else if current date >= ((first sunday of current month_and_year) + (28*day)) then "5" else "Undefined") = (if exist values of settings "Patch Week" of client then value of setting "Patch Week" of client else error "not set") and day_of_week of current date as string = (if exist values of settings "Patch Day" of client then value of setting "Patch Day" of client else error "not set") and ((two digit hour of it as string & two digit minute of it as string) of time (local time zone) of it) of now >= (if exist values of settings "Patch Start Time" of client then value of setting "Patch Start Time" of client else error "not set") and ((two digit hour of it as string & two digit minute of it as string) of time (local time zone) of it) of now <= (if exist values of settings "Patch End Time" of client then value of setting "Patch End Time" of client else error "not set") then True else False

In short, what this relevance does is examine the values of all the client settings above and compare them to the date on the client’s clock. Like tumblers in a lock, if all the client settings align (Week-of-the-month, day-of-the-week, time-of-day) the property will evaluate to

This all happens automatically every day of every week of the month.  Depending on their user-defined values the property will show ‘True’ for some clients and ‘False’ for others.

Now you have a single property that you can use in the ‘Run only when’ constraint within your single action to limit when and for how long that action runs on your clients. 

By targeting your action to all devices and limiting when it can be executed using the “Run only when” constraint you can start a single action on the first day of of the month and allow it to run for however long your patching cycle is.  Only clients whose patch window value is ‘True’ will execute the action. All others show as status ‘Constrained’ until such time as their clock times align with the patch window.

By using this method you are actually creating pseudo maintenance windows for each different combination of Week/Day/Time you set on your clients. The biggest difference between this and the built-in maintenance window functionality is that:

  • Other than creating the client settings and selecting the property in the action parameters you don’t have to do anything else to enforce the patch window on your clients
  • You can dynamically alter which clients obey which patch window by simply editing the client settings that pertain to its patch window date
  • Most importantly, your clients are not always locked which means that you can force a specific action to execute only during a pre-defined time window, but still perform other actions on the devices since they are unlocked.

Some things to note before you go off and use this:

  • This has worked well in various customer environments I have deployed in; however, for each implementation I have had to modify the “Patch Window Property” to match how the customer defines their patch window.  As such, take the example above and use it as a template for your own needs.  In the relevance code above the Patch Weeks are defined as beginning with the “first Sunday” of that month and the week numbers start at ‘0’.  You may define your own patch weeks as starting with number ‘1’ and beginning on the first Tuesday of the month.  Or you may patch for the entire week and not a single day.  The point is:  what’s more important when you think about doing this is the concept rather than the specific execution.
  • If you are at all familiar with relevance you know that there are 12 ways to write relevance that gives you the same result.  In looking at the way I wrote the relevance for the property above you may see places where it can be made shorter and more efficient.  First I would say: have at it.  I’m always looking for ways to write more efficient code; however, be aware that what you see above is the result of several dozen iterations of the relevance clause.  In earlier versions it was more compact, but I found that it didn’t always work as expected and so I wound up with what you see above.  In this instance it was more important that it always work rather that it have a smaller footprint or evaluation time.
  • Lastly, BigFix is always improving functionality.  There may come a time when some change to the BigFix inspectors may make this relevance work differently than it was intended.  Because I use it quite a bit I will likely know if this happens, but after every platform upgrade you should test that this is still working as expected.

[1] Image sourced from: https://pixabay.com/photos/button-buttons-computer-design-key-2076/