Running Windows Updates Manually via CF-Engine

74 views
Skip to first unread message

p...@stampedepress.org

unread,
Jun 2, 2016, 3:48:07 PM6/2/16
to help-cfengine
Hi, I've been trying to find help with a script to run Windows updates on my Windows 2012R2 and 2008 servers. I had an issue a while ago where a Windows update ran and then locked up some key services because the system needed a reboot. These servers are hardly logged into, they just run. So I set all the Windows update functionality to manual and I'm hoping to just run a script via CF-Engine to get them all running at the same time. 

None of the scripts I found online worked for updating my local 2012R2 system, are there any good resources anyone could point me to? 
This was one of the ones I found listed:


Thanks,
P

Nick Anderson

unread,
Jun 2, 2016, 4:19:27 PM6/2/16
to p...@stampedepress.org, help-cfengine
I think you will want to execute the windows updater as a commands
promise. What happens if you run `wuauclt.exe /detectnow /updatenow`
with the current manual settings?

I have also come across wuinstall which might be a good thing for
CFEngine to drive.


signature.asc

Natxo Asenjo

unread,
Jun 2, 2016, 4:38:30 PM6/2/16
to Nick Anderson, p...@stampedepress.org, help-cfengine
hi,
in my experience neither wuauctl and wuinstall are very stable. Using this powershell module(1) I have had much better results but I do not use cfengine in windows (yet).

(1) https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc

--
regards,
natxo

Nick Anderson

unread,
Jun 2, 2016, 4:45:43 PM6/2/16
to Natxo Asenjo, Nick Anderson, p...@stampedepress.org, help-cfengine
On 06/02/2016 03:38 PM, Natxo Asenjo wrote:
> in my experience neither wuauctl and wuinstall are very stable. Using
> this powershell module(1) I have had much better results but I do not
> use cfengine in windows (yet).
>
> (1)
> https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc

Thanks for the link and the note Natxo. If you have had good results
with the above powershell scripts I assume we would be able to automate
with them using commands promises with a contain body that has
useshell(1) set to powershell.

(1)
https://docs.cfengine.com/lts/reference-promise-types-commands.html#useshell

signature.asc

p...@stampedepress.org

unread,
Jun 3, 2016, 3:18:27 PM6/3/16
to help-cfengine
Hi Nick, I didn't have much luck with  wuauctl. I looked and apparently this won't work if you have "Never Check for updates" selected. (http://superuser.com/questions/462425/can-i-invoke-windows-update-from-the-command-line)

Hi Natxo I was able to install the module but can't seem to figure out how to run it. What is the command to trigger the update?

Yea Nick that would be great, triggering this script with CF-Engine would make it super convenient.What do you think about the setup, I would need the module installed on each server and then CF would just run the command on each server, right?

Thanks guys for your help.

Nick Anderson

unread,
Jun 3, 2016, 3:21:52 PM6/3/16
to p...@stampedepress.org, help-cfengine
On 06/03/2016 02:18 PM, p...@stampedepress.org wrote:
> Hi Natxo I was able to install the module but can't seem to figure out
> how to run it. What is the command to trigger the update?
>
> Yea Nick that would be great, triggering this script with CF-Engine
> would make it super convenient.What do you think about the setup, I
> would need the module installed on each server and then CF would just
> run the command on each server, right?

Right, I would probably distribute the powershell scripts to each
windows server using a copy_from files promise, then use commands
promises to execute them as needed. You might need to make yet another
small wrapper if you want more info from the scripts (defining
variables, or classes) with the module protocol.

signature.asc

Paulus Smit

unread,
Jun 6, 2016, 7:52:47 AM6/6/16
to Nick Anderson, p...@stampedepress.org, help-cfengine
Hi

I make the following registry entrys (on the workstations), to set the auto install of the updates:

 "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update"
        comment => "create registry key for congiguration Windows Update",
        database_operation => "create",
        database_rows => {
                         "IncludeRecommendedUpdates,REG_DWORD,00000001",
                         "AUOptions,REG_DWORD,00000004",
                         "ElevateNonAdmins,REG_DWORD,00000001",
                         },
        database_type => "ms_registry";



For the servers I sent them to my wsus server (scheduled the updates there):

 "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"
        comment => "create registry key's to connect to the WSUS server ",
        database_operation => "create",
        database_rows => {
                         "WUServer,REG_SZ,http://<servername>:8530",
                         "WUStatusServer,REG_SZ,http://<servername>:8530",
                         },
        database_type => "ms_registry";

Paulus



----- Oorspronkelijk bericht -----
Van: "Nick Anderson" <nick.a...@cfengine.com>
Aan: p...@stampedepress.org, "help-cfengine" <help-c...@googlegroups.com>
Verzonden: Vrijdag 3 juni 2016 21:21:46
Onderwerp: Re: [help-cfengine] Re: Running Windows Updates Manually via CF-Engine
--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengin...@googlegroups.com.
To post to this group, send email to help-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/help-cfengine.
For more options, visit https://groups.google.com/d/optout.

p...@stampedepress.org

unread,
Jun 7, 2016, 9:09:09 AM6/7/16
to help-c...@googlegroups.com
Thanks Paulus Thanks Nick,

 I was able to find partial success using the powershell module Nick suggested. It's my first time using powershell modules so there was some learning curve. This site really helped me get everything going, (https://www.petri.com/manage-windows-updates-with-powershell-module). 

 Now I'm working on the 2nd part of the equation which is having CF-Enigine run the powershell script only when run manually. Are there any guides anyone can recommend, something from scratch because this project is my first CF-Engine setup.
 Is it possible to just have this script saved locally to run manually via cf-agent. Or should I add this to be distributed to each system via promises.cf? I'm not sure how to structure the syntax in this case where I don't want the updates run every 5minutes when CF-Engine checks status on my-policy.cf

Thanks!,
P
 

Nick Anderson

unread,
Jun 7, 2016, 9:19:20 AM6/7/16
to help-c...@googlegroups.com
On 06/07/2016 08:09 AM, p...@stampedepress.org wrote:
> The theory I'm currently going on is I'm writing a policy that is just
> going to live in a seperate folder on primary server, and it won't be
> linked in the promises.cf file. That way I can trigger it using
> cf-agent manually when I choose to run the updates.

Great, it would be useful if you could gist your work in progress.

You can define classes when you execute the agent or when you execute
cf-runagent (I almost never use runagent myself).

cf-agent --define allow_windows_update

cf-runagent --hail <ip> --define-class allow_windows_update

That way you can wire it into your normal policy.


bundle agent example
{
methods:

allow_windows_update::

"My windows update bundle" -> { "SecOps" }
usebundle => my_windows_update_bundle,
comment => "We want to stay on top of the never ending stream
of security patches.";
}

signature.asc

Paulus Smit

unread,
Jun 7, 2016, 9:36:01 AM6/7/16
to p...@stampedepress.org, help-cfengine
hi,

An idea for use powershell modules:
"\"C:\Windows\syswow64\Windowspowershell\v1.0\powershell.exe\" -NoProfile -ExecutionPolicy Bypass -Command C:\_install\subtrac\powershell\Install_keepass.ps1";

Paulus



Van: p...@stampedepress.org
Aan: "help-cfengine" <help-c...@googlegroups.com>
Verzonden: Dinsdag 7 juni 2016 15:09:08
Onderwerp: [help-cfengine] Re: Running Windows Updates Manually via CF-Engine

Thanks Paulus Thanks Nick,
 I was able to find partial success using the powershell module Nick suggested. It's my first time using powershell modules so there was some learning curve. This site really helped me get everything going, (https://www.petri.com/manage-windows-updates-with-powershell-module). 

 Now I'm working on the 2nd part of the equation which is having CF-Enigine run the powershell script only when run manually. Are there any guides anyone can recommend, something from scratch because this project is my first CF-Engine setup.
 The theory I'm currently going on is I'm writing a policy that is just going to live in a seperate folder on primary server, and it won't be linked in the  promises.cf file. That way I can trigger it using cf-agent manually  when I choose to run the updates. 

Thanks!,
P
 

On Thursday, June 2, 2016 at 3:48:07 PM UTC-4, p...@stampedepress.org wrote:

--

p...@stampedepress.org

unread,
Jun 16, 2016, 12:20:02 PM6/16/16
to help-c...@googlegroups.com
Hit some delays due to other work projects but I'm back on track for setting up my CF-Engine script. 
 OK, so I've got the windows update module working in PowerShell via this command: " Get-WUInstall –MicrosoftUpdate –AcceptAll –AutoReboot"
  Then I have a basic script in CF-Engine on my Windows Server which will output text in Powershell. 

"body common control 
 {
bundlesequence => {"WinUpdate"};
}

bundle agent WinUpdate
 {
 vars: "mymessage" 
  string => execresult("Write-Output Running Update on Windows Servers", "powershell");
 
reports: "$(mymessage)"; 

// This doesn't work,
//execresult("C:\temp\scripts\WinUpdate.ps1", "powershell");
}
"
 Now I'm trying to figure out how to run the powershell script through my CF-Engine script. Once I get this going I'm going to work on triggering the script remotely and ultimately triggering the script remotely and having it run on several Windows servers. 
 Few steps still to go, does anyone have any advice for running a powershell script file through CF-Engine? I've been watching whatever I can find on youtube and reading as many sites as I can find but still no clear answer on this. I do see a work around for running a .bat file but would like to avoid going that route. 

 Also Nick I appreciate your post about Classes, that is definitely coming in handy once I get this script working locally. 

Nick Anderson

unread,
Jun 16, 2016, 12:32:56 PM6/16/16
to p...@stampedepress.org, help-cfengine
On 06/16/2016 11:20 AM, p...@stampedepress.org wrote:
>
> // This doesn't work,
> //execresult("C:\temp\scripts\WinUpdate.ps1", "powershell");
> }
> "
Does it error?

Do you need to capture the output from the command? Maybe you just need
to execute it? If so then you should be able to use a commands promise.

https://docs.cfengine.com/docs/3.9/reference-promise-types-commands.html#useshell

bundle agent example
{
commands:
"C:\temp\scripts\WinUpdate.ps1"
contain => powershell;
}

body contain powershell
{
useshell => "powershell";
}


signature.asc

p...@stampedepress.org

unread,
Jun 17, 2016, 11:56:23 AM6/17/16
to help-cfengine, p...@stampedepress.org
Thanks Nick, that worked out great.

Here's the script I ran in the end,

body common control 
 {
bundlesequence => {"WinUpdate"};
}

bundle agent WinUpdate
 {
 vars: "mymessage" 
  string => execresult("Write-Output Windows Update has been run and completed", "powershell");
 
reports: "$(mymessage)"; 

commands: 
  "C:\temp\scripts\WinUpdate.ps1" 
    contain => powershell; 

body contain powershell 
  useshell => "powershell"; 
}

I chose to keep the message in there, because sometimes the script ran and output no result, if there were no updates needed to be run. So just kind of a heads up to the user that things did work, and this server is good to go. 

It's like, Wow, huge step accomplished right there.
Now I'm going to work on triggering this script from my primary CF-engine server. So the script on my Windows server is in promises.cf, and I want it to get triggered manually from my host CF-Engine server. The end goal is that I want to update multiple Windows and Linux servers at the same time with a single command. ..I think I need to brush up on my CF-Engine theory before I continue.

Nick Anderson

unread,
Jun 17, 2016, 1:55:45 PM6/17/16
to p...@stampedepress.org, help-cfengine
On 06/17/2016 10:56 AM, p...@stampedepress.org wrote:
> It's like, Wow, huge step accomplished right there.
> Now I'm going to work on triggering this script from my primary
> CF-engine server. So the script on my Windows server is in promises.cf,
> and I want it to get triggered manually from my host CF-Engine server.
> The end goal is that I want to update multiple Windows and Linux servers
> at the same time with a single command. ..I think I need to brush up on
> my CF-Engine theory before I continue.

You could, in services/main.cf:

```
methods:
windows.allow_windows_update::
"Windows Updates" -> { "SecOps" }
usebundle => WinUpdate,
comment => "We want to keep current on our windows patches for
security, but only during allowed periods so that we do not unexpected
downtime.";
```

Then you can decide if you want to automatically define
"allow_windows_update":

```
bundle common example
{
classes:
"allow_windows_update" expression =>
"Tuesday.(Hr00|Hr01|H02|Hr03|Hr04|Hr05|Hr06)";
}
```


Or you could rely on maual action with cf-runagent.

cf-runagent --define-class allow_windows_update --hail <ip of windows host>

Maybe you will want to run with -v or -I to get some extra info.

Additionally I would guard your "mymessage" vars promise to windows::
(assuming you have non windows hosts in your environment).

And you should always guard reports with something. I like to use
DEBUG|DEBUG_bundlename

in 3.7+ you can actually do:

```
reports:
"DEBUG|DEBUG_$(this.bundle)"::
"DEBUG $(this.bundle): Message '$(mymessage)'";
```

Though I still generally do it explicitly for each bundle:

```
reports:
DEBUG|DEBUG_my_bundle::
"DEBUG $(this.bundle): Message '$(mymessage)'";
```




signature.asc

p...@stampedepress.org

unread,
Jun 20, 2016, 9:55:46 AM6/20/16
to help-cfengine, p...@stampedepress.org
I commented out the previous script I had setup on my policy server, just so it's a clean start. 
I then tried running the manual command, but that resulted in: 

[root@llgen-CFE inputs]# cf-runagent --define-class WinUpdate --hail -v 10.253.160.135

   error: Can't stat file '10.253.160.135' for parsing. (stat: No such file or directory)


Would I need to add anything to the Policy server in order to help it along, or it should just trigger the script remotely?

I haven't added promises.cf to anything on the Windows side since I figured this was the default master file.  


Nick Anderson

unread,
Jun 20, 2016, 10:56:08 AM6/20/16
to help-c...@googlegroups.com
On 06/20/2016 08:55 AM, p...@stampedepress.org wrote:
> [root@llgen-CFE inputs]# cf-runagent --define-class WinUpdate --hail -v
> 10.253.160.135
>
> error: Can't stat file '10.253.160.135' for parsing. (stat: No such
> file or directory)
>
>
> Would I need to add anything to the Policy server in order to help it
> along, or it should just trigger the script remotely?
>
> I haven't added promises.cf to anything on the Windows side since I
> figured this was the default master file.
>

You will need to make sure the policy file that contains WinUpdate is
included in your policy set. And then you need to reverse the order of
-v and --hail.

cf-runagent --define-class WinUpdate -v --hail 10.253.160.135


signature.asc

p...@stampedepress.org

unread,
Jun 20, 2016, 3:19:10 PM6/20/16
to help-c...@googlegroups.com
Thanks Nick. Is there anything to look out for, so that it doesn't run on my regular refresh interval? 
So I only need to add WinUpdate in promises.cf, right?

I keep getting an error "Duplicate Definition of body control with type common", it maybe conflicting with the former my-policy.cf I had set up.

Nick Anderson

unread,
Jun 20, 2016, 3:26:31 PM6/20/16
to help-c...@googlegroups.com
On 06/20/2016 02:19 PM, p...@stampedepress.org wrote:
> Thanks Nick. Is there anything to look out for, so that it doesn't run
> on my regular refresh interval?
> So I only need to add WinUpdate in promises.cf, right?

In addition to adding it to inputs, you need to arrange for it to run
from your policy, but you want to guard it with a class that is not
defined under normal conditions. 3.9 adds the ability to specifically a
specific bundle with cf-runagent so you wouldn't have to do this so long
as you allowed the bundle to be run with runagent.

For example:

services/main.cf
bundle agent main
{
methods:

all_the_kings_horses_and_all_the_kings_men_couldnt_put_windows_together_again::

"Windows Update"
usebundle => WinUpdate;

}


So in that example, the WinUpdate bundle won't run unless the class
all_the_kings_horses_and_all_the_kings_men_couldnt_put_windows_together_again
is defined.

signature.asc
Reply all
Reply to author
Forward
0 new messages