Friday, April 27, 2012

One Liner to Patch an Offline Win7 Image

Keeping the base image for desktop deployments up-to-date with patches is important, if anything to avoid the inevitable super long patch session when it either first comes online or hits the first patch distribution cycle of its life.  The other day I was just trying to figure out if it was possible to do it in one line - not because that's necessarily useful (it's not), but mostly because I just like goofy stuff like this.  This assumes that you have cab files downloaded via WSUS or some other method and dropped in a directory and that your image is already mounted to F:\WIMMount.  Change the "x86" to "x64" if you're patching a 64-bit image.

C:\Program Files\Windows AIK\Tools\x86>forfiles /s /p F:\WSUS\UpdateServicesPackages\ /m *x86*.cab /c "cmd /c dism.exe /image:F:\WIMMount\ /Add-Package /Packagepath:@file"

Thursday, April 26, 2012

Active Directory Security Event Log Monitoring with Powershell + Nagios

For the longest time I've been using a strange combination of snmptt, a duct tape perl script, and Nagios to monitor basic security events in a Windows 2003 domain - basically, the DCs would push SNMP events for failed logins and locked accounts to snmptt and the Nagios check would run the script that parsed the snmptt log over a period of time to determine whether or not there have been too many failed logins or locked accounts (indicating an account problem or a brute force attempt). 

I've always hated this, but I think as a rule I always hate the first way I do something because it always looks entirely ridiculous in hindsight.

So, while in the process of migrating Nagios to a different server, I decided it was time to cast off the shackles of SNMP and do this a little more sanely (if redoing it in Powershell can be considered sane).  A co-worker of mine has been lauding Powershell as the second coming for quite a while so I decided to dive in and really it ain't bad. 

For example, just to get the events I wanted during the timeperiod I wanted (i.e. in the last hour):

$events = get-eventlog -logname security -EntryType FailureAudit -After (Get-Date).AddMinutes(-60)

I learned a few little oddities about security logging while doing this - for example, EventID 675 (Pre-authentication Failure) with a Failure Code of 0x19 is an artifact of having newer client machines (in this instance, Win7) attempting an encryption method not compatible with a 2003 domain - the system will try a compatible method immediately afterwards.  So, those can be safely ignored by adding an if statement / whatever that strips those out (note: all the meaty parts of the event are stored in the replacementStrings array of the event object - unfortunately, since each EventID stores different info in the message there is no rhyme or reason to what data will be where in the array and you have to set up some per EventID filtering to get the data you want):

$event.replacementStrings[4] -ne "0x19"

But wait!  EventID 672 (Kerberos authentication ticket request) with a Result Code of 0xE appears to be a similarly ignorable issue but from a different source - looks like it might be coming from ActiveSync in my case.  So, the if statement can be updated (of course the 672 events put the Result Code in a different part of the replacementStrings than 675...):

$event.replacementStrings[4] -ne "0x19" -and $event.replacementStrings[6] -ne "0xE"

So if you've been messing around with this to see how it looks, depending on where you're running it you may have noticed an inordinately long pause after it returns the results - in my case, the pause is about 60-90s (and this only occurs on my DCs).  I have no idea why that is - my guess is that it checks at least some of the other events in the log to see if their timestamp is prior to the time listed in the -After switch (thus negating some of the usefulness of the switch).  If anyone has a more solid answer to that I'd love to hear it.

Once you have the data you want out of the event log it's pretty easy to get it back to Nagios - like any other script as long as you write a line of text and Exit with the right return code you've got a good chance of success.  I've recently switch to NSClient++ after years and years of using NRPE on Windows and I must say I much prefer it (and it's still actively developed which doesn't hurt at all).  Using the premade config option for wrapped Powershell scripts (ps1=cmd /c echo scripts\%SCRIPT% %ARGS%; exit($lastexitcode) | powershell.exe -command -) I just added it to the scripts directory and added a directive in wrapped scripts and it works dandily (note that if you try to do a more common syntax to call Powershell like powershell.exe -File script.ps1 NSClient++ will just go out to lunch, so don't try to get fancy).

Voila!

# ./check_nrpe -H domaincontroller -c check_failed_logins -t 120
OK: 55 events generated since 7:51 AM


I'll add the whole script to http://exchange.nagios.org/ later and link it here for anyone that's interested.

Brief Introduction

I recently read a blog where someone had a philosophy of blogging anything that took them longer than an hour to fix.  I've decided that I'm going to co-opt that philosophy.  Lately I've been stumbling across a lot of odd problems in my day to day endeavors as a sysadmin, so what better way to give back to the internet that I syphon off of daily than to (hopefully) help someone in the future.

I spend most of my days managing a little bit of everything - Windows, Linux, Unix, OpenVMS, SANs/fabrics, VMWare - so there may be little to no consistency in what's posted here.