How to attach a custom task to an event on WS08

In an earlier post I talked about how to forward events from one machine to another. That works out quite well, but unless you’re sitting at the log and watching the events go by, you might miss something. You might agree that there are some events that you are more interested in than others. For example, while it’s neat that Windows let’s you know server uptime in seconds as an event but I’d be much more interested in an event related to a computer that is unable to establish a trust relationship with it’s domain controller.

For details on Event 5722

The nice thing about Windows Server is that you can set up a custom task to let you know when a particular event occurs. This doesn’t really replace any sort of quality monitoring software like System Center Operations Manager or Zenoss, but it’s most certainly a nice thing to have built-in. So how do you go about setting this up? In my example I’ll be creating a task that sends me an email based on an event forwarded from my domain controller. It will require a script, but I’ll include it for you.

First thing is to have a script that writes the event to a file. The reason is there is sadly no built-in feature to pull the event details and put it into an email task. So we’ll have two tasks that run, one that runs the script to make the file. The second to take that file as an attachment and email it to you.

Option Explicit

Const ForWriting = 2
Dim strComputer
Dim strEventCode
Dim objWMIService
Dim objEvents
Dim objEvent
Dim objFSO
Dim objFile

strComputer = “.”
strEventCode = CInt(Wscript.Arguments.Item(0))

Set objWMIService = GetObject(“winmgmts:{(Security)}\” & strComputer & “rootcimv2”)
Set objEvents = objWMIService.ExecQuery(“Select * from Win32_NTLogEvent where logfile=’system'”)
Set objFSO = CreateObject(“Scripting.FileSystemObject”)

If objFSO.FileExists(“C:scripts” & strEventCode & “.txt”) Then
    Set objFile = objFSO.OpenTextFile(“C:scripts” & strEventCode & “.txt”, ForWriting)
Else
    Set objFile = objFSO.CreateTextFile(“C:scripts” & strEventCode & “.txt”)
End If

For Each objEvent in objEvents
    If objEvent.eventcode = strEventCode Then
        objFile.WriteLine objEvent.eventtype
        objFile.WriteLine objEvent.eventcode
        objFile.WriteLine objEvent.message
        Wscript.Quit
    End If
Next

The script above is very simple. It accepts a single command-line parameter, the event code. It connects to the WMI service of the local computer and pulls in the System log. Then it checks to see if there is a file named for the event code in the scripts directory, if not it creates one, otherwise it overwrites the existing one. Then inside the For Each loop, we find the first event code that matches the provided code, and write out the type, code and message and then exit out of the script altogether.

Now we need to find a task that we are interested in getting notified about, and attach a task to it. The first thing you need to do is head over to the event viewer, and right-click on a task.

20100930-attachtask

Fortunately a wizard will guide you through the entire process. The first thing you need to do is provide a name for your task that makes sense for you.

20100930-taskwizard

Since we selected a specific event from the log, we are unable to edit the event to log.

20100930-loggedevent

The next thing we need to do is pick what action we want to trigger when our event shows up. There are three options; Start a Program, Send an email or Display a Message. The first time through we will choose, Start a Program.

20100930-taskaction

Then you need to specify the options for your program. You can browse to the program you wish to run, I have selected the above script as my program. Since my script accepts an argument I set the argument of my script.

20100930-scriptaction

You can click through the remaining screens and your custom task is now set. The next step is to associate our second task to this event. The second task is to email the file that gets created as an attachment to yourself. Go through the first series of steps like we just did for the script, except we will choose Send an Email.

Fill in all the needed details for your email message and browse to the folder where your attachment is created.

20100930-emailtask

Again click through the remaining screens to save our email task, and as soon as the event your are interested in appears you should have an email.

Forwarding Events from WS08 Core DC

There was some changes between Windows Server 2008 and Windows Server 2008 R2, the one I’m interested in is WinRM. The default HTTP port on Windows Server 2008 is TCP 80, but on Windows Server 2008 R2 the default HTTP port is TCP 5985. There are a couple of ways to get around this; either change the listener port on the Windows Server 2008 machine, or use a Collector Initiated subscription and change the port on the Advanced tab. In my example these computers are both Domain joined. Setting this up in a Workgroup environment is a little different and I may write up something for that later.

Configuring the Source (Windows Server 2008 Core)

Verify that the WinRM is either on or off

winrm e winrm/config/listener

20100922-SourceWinRMDisabled

Here you can see that WinRM is not configured. So now we need to enable WinRM

winrm qc

20100922-SourceWinRMEnabled

The quickconfig (qc) option does the initial configuration of WinRM. It creates an HTTP listener on port 80, and enables firewall exceptions. In order to connect from the Collector and start getting events we also need to allow the remote administration service through the firewall.

netsh firewall set service type=remoteadmin mode=enable

20100922-SourceFirewallExceptionsOn

The configuration of the source server is done.

Configuring the Collector (Windows Server 2008 R2)

In order for this server to pull information from the Source you will need to setup a subscription

Start > Administrator Tools > Server Manager > Diagnostics > Event Viewer > Subscriptions

20100922-CollectorEnableWCESVC

You will notice that before you can setup a Subscription you need to enable the Windows Event Collector Service, click Yes. Now you can click Create Subscription from the Action pane on the right. At the very least you will need a Subscription name.

20100922-CollectorSubscriptionProperties

We are going to configure a Collector initiated subscription, so browse the Directory and find your Source server. If you click the Test button, you may receive an error message that lets you know the Collector can’t talk to the Source. That’s ok, we’re going to fix that in a minute.

20100922-CollectorSubscriptionError

Now we need to configure the list of Events that we are interested in. These are the default events available on any 2008 computer, you can write an XML query that you can paste into the XML tab.

20100922-CollectorSubscriptionEvents

The last thing we need to configure is the Protocol settings and Delivery Optimizations. If your Source server is not a Domain Controller then you can add the computer account of the Collector to the Local Administrators group on the Source. If your Source server is a Domain Controller, you may want to use a Service Account.

I set my Event Delivery Optimization to Minimize Latency, this ensures that events are delivered with minimal delay. If you are collecting events from the Security log, this may not be a setting you want to enable.

Finally the Protocol section, here you can change the HTTP port to 80.

20100922-CollectorSubscriptionAdvancedProperties

After a few minutes you should start to see events showing up under Forwarded Events.

20100922-CollectorForwardedEvents

Windows Server 2008 R2 and Print Logging

Yesterday I got a support ticket that stated the user was unable to connect to any printers on the network. I found this odd since we push out printers via GPO Preferences, and that user’s particular computer had the correct GPO linked in. So I started my troubleshooting process which usually involves grep’ing the logs looking for relevant entries.

We have two print servers, one is running Windows Server 2003 R2 and the other is running Windows Server 2008 R2. Both have about 40 odd printers installed, and that is their sole purpose in life. One of the things we realized a long time ago is that the event logs for Windows printing is really horrible. So we have downloaded and installed the PaperCut Print Logger software.

I noticed that he had connected to the print server earlier that morning to print, but nothing since. So I decided to check in the system log, which is where I would go on Windows Server 2003. I was surprised to see there were no entries related to printing at all, then I noticed there was a view for Roles, and that Print and Document Services was an option to view.

When I looked through that log, I noticed that the only events in it were related to installing printers and their associated drivers. So opening up the Applications and Services Logs folder, expanding the Microsoft folder, expanding the Windows folder,  and scrolling down to PrintServices I found an Operational log, that had nothing in it. When I opened that log up I noticed that from the list of Actions I could Enable Log, once I did that I started seeing entries show up.

It turns out the default setting for this log is off, even if you pick the File and Print server role which seems a bit counter-intuitive to me. So remember, when setting up your print server on Windows Server 2008, to enable logging perform the following steps:

  1. Login to the server
  2. From Server Manager, expand Diagnostics and Event Viewer
  3. Expand Applications and Services Logs
  4. Expand the Microsoft folder, expand the Windows folder
  5. Expand the PrintServices folder
  6. Right-click on the Operational Log, and click Enable Log

Managing your network interfaces for VMWare Player

If you need to reconfigure your virtual network, you will need the vmnetcfg.exe utility. This is part of the VMware Player download, but you have to run the installer such that it only extracts it’s files. Once you have extracted the files to a temporary folder, you will then need to extract the network.cab file. This cabinet file contains almost everything you need.

In the temporary folder that contains all the VMware player files, you will need to copy the following files to the same location you extracted the network.cab file to.

  • sigc-2.0.dll
  • vmwarebase.dll
  • libxml2.dll
  • iconv.dll
  • zlib1.dll
  • vmwarecui.dll
  • glib-2.0.dll
  • intl.dll
  • gobject-2.0.dll
  • glibmm-2.4.dll
  • gmodule-2.0.dll
  • vmwarestring.dll
  • libcurl.dll
  • ssleay32.dll
  • libeay32.dll
  • libldap_r.dll
  • liblber.dll
  • vmwarewui.dll
  • vixdiskmountapi.dll
  • sysimgbase.dll
  • vnetlib.dll

Once all the supporting files are in the same folder as the vmnetcfg.exe file, you will be able to manually adjust the virtual network adapters.

Working with computer objects

So I’m working with computer objects, if you can’t tell from my previous post. There are times when what you really want to know about a given computer is, who’s responsible for it. With good user education, your OU admins or computer admins will pre-stage a computer and populate the ManagedBy property. This effectively lets anyone who can read that property, know who is responsible for this object.

In an environment with thousands of computers, or even hundreds of computer’s the likelihood of this actually happening is most likely very slim. I freely admit that when I create a computer object, I leave that field empty. But it’s ok, if you have given your users the right to join their own computers to the domain this information is stored in the ACL for the object.

I got to write a new function that pulled the owner from the ACL. I found what I was looking for in the Technet Forums. The only thing I changed was making the stand-alone script a function that I could pull into my code. The output is the username formatted NT-style:

DOMAINUsername

I wrote a couple of scripts today around the managedby property. The first script walks through your ActiveDirectory and reports out the name of the computer and who the owner is. If you have a domain admin account and created that object then the owner becomes Domain Admins. If a non Domain Admin created the object, that account is listed as the owner.

The best way to run this particular script is as follows:

cscript //nologo GetOwner.vbs > ComputerOwners.csv

The resultant output file can be opened up in the spreadsheet program of your choice, and will have two columns. The name of the computer, and the DomainUsername of the owner. You will want to change the LDAP URI at the top, to point at the OU of your choice within your domain, or for fun point it at the root. This script does not modify anything at all, and can be run as a regular non-admin user.

That was the first part of what I needed, a way to get the user who owned the computer. For the next script, I needed was a way to write that information into the managedby property of the object. The only issue I had was that the username was reported NT4 style, and I needed to store it as a DN. So I got to write a second function that converted the NT4 username to a DN string.

I found the code on the Scripting Guys blog. The actual code from the blog returns a GUID, but they kindly added a table at the bottom that listed the other formats that could be returned from IADsNameTranslate. I modified the code to return ADS_NAME_TYPE_1779, and changed it from a stand-alone script to a function that returned the DN of the user.

There is no output in this script, it just runs and sets as it goes. If you have a problem with that, one thing you can do is change the line that reads:

Call WriteData(strADSIProp, strUserDN, strComputerPath)

To

Wscript.Echo "Changing " & strADSIProp & " property of " & strComputerPath & " to " & struserDN

This will output a line that will tell you what the script will do. Personally I would comment out the call to WriteData and add the Wscript.Echo as a new line below that. Once you are satisfied that it works the way you anticipate, delete that echo line and uncommenet the call.

Active Directory Naming Strategy

Does anyone have a good naming convention for Active Directory? It’s all completely subjective, what works for one organization is absolutely horrible for the next. Does anyone document what their naming convention is? Perhaps a better question would be, if you document it, do you follow it? How many people are aware of the 15 character limit on Window’s NetBIOS hostnames? How many know that limitation is still painfully applicable?

What are the reasons for having a naming convention? Answering this may help you determine one that works for you. If you want to be able to physically locate a machine based on it’s name that will lead you to a completely different convention than if you just wanted to track asset information. In our case, we wanted to move away from the previously undocumented convention. It seemed to a combination of the previously mentioned examples.

Computers that were created under the previous convention were named something akin to the following:

DEPT-Room-Station

That kind of worked, but we currently manage computers 4 buildings so there was no way to know what building a given machine was physically in. We could figure out which buildings it wasn’t in, based on the number of floors in each, but as you can guess this didn’t work well. We needed something that a brand new employee could translate easily without having to know what building and floor each of the departments happened to be in.

What we settled on was relatively simple:

Building-Room-Station

Building is a one-letter designation for any of the four buildings we have computers in:

  • Burt – B
  • Eaton – E
  • Learned – L
  • Regents – R

The room number is between 3 and 5 characters long. This gives us the ability to have an office that is 123 or 1123A. Finally Station, that is typically a 4 character code that determines what computer in a room of several, this particular computer is. It also differentiates between a laptop and desktop, which originally I was opposed to, but really wound up working out well later.

  • Laptop 3 – LT03
  • Desktop 31 – PC31

So, for example the third laptop in the second floor office 2100-A of Burt Hall would have the following name:

B2100a-LT03

It’s pretty simple to figure out, it doesn’t reference anything that we don’t care about and fits nicely inside the 15 character NetBIOS limit.

But let’s be honest, does that really matter? Sure, it works wonderfully when the computer is initially setup but around here, computers have acquired locomotion! This year B2100a-LT03 might actually be in that office, but maybe the professor gets moved to an office on the 4th floor of Learned. Does his computer magically stop working because it’s in the wrong room? Don’t you wish! Of course not, that computer will continue to chug along it’s merry way, never knowing it did anything more interesting than a reboot.

So the real problem I think is enforcement. Which around here always seems to be the real problem. How do you enforce a naming convention around here? Well, we decided that the easiest way is to not worry about it. Computers move, when we receive a support request from B2100a-LT03 we will walk over to Burt, walk into that office and see the computer is no longer there.

In this situation, ideally, the tech would then contact the owner and find out what office they are currently located in. The technician would then check Active Directory to see if the new name is already taken. If it is, we simply increment the station number. So as part of the service call, the technician will logon using her admin account, rename and reboot the computer. Problem solved and we can move on with our life.

Does anybody really know what time it is?

Or, How to fix your Novell clients so they don’t get hosed up times!

If you don’t know this, when a computer in an Active Directory domain gets an invalid time it stops working. It has to do with Kerberos tickets and time stamps, and really it’s all very boring. Suffice it to say, that is the reason there is a w32time service. By default, Windows clients in a domain sync their clocks to the domain controllers.

But something interesting happens when you add the Novell client into the mix. I want to state for the record, I have almost no experience with Novell, nor do I care for the product. In my experience, once the Novell client is added it appears to over-ride the default behaviour of Windows and force a time-sync with it’s own server. Aside from the obvious problems one would have with that particular arrangement, the next thing that seems to happen is, for no apparent reason the client will get the wrong time. Check out the image below of one very sad and confused computer.

20100913-time

Like I said earlier, I claim no ability to admin a Novell server at all, it’s just not my thing. One thing I have been assured of is that the time on the Novell server is correct, and I have no reason to believe otherwise. The internet says that we should load up the latest service pack, sadly we’re already there. The internet also says we should change the default settings of the Novell client.

HKLMSOFTWARENovellNWGINALogin ScreenSynchronize Time = 0 (REG_DWORD)

We just rolled that out, I am fairly certain that will take so I don’t think I’ll worry about this again. To be quite honest the only reason I’m even posting is because I really enjoy the image above, and I hope you do as well!

The usefulness of TCPDUMP

We are mid-firewall migration, it’s set to happen in about 2hrs from this post. But in the middle of trying to figure out why we are getting crazy network outages, we ran tcpdump on our dns/dhcp server. Why that server? That was the server that was identified by Central-IT as having issues.

We only ran tcpdump for a few minutes and in that time we got some very interesting results. It appears that another entity on campus is hammering our dns server with known bad dns zones. I filtered on just that subnet, selected those packets and exported it to a csv. We have a plotter, so of course the next thing to do was plot it out! Sadly, Excel decided to add page-breaks…sigh

There were 23,000 packets captured and this entity accounted for 4,400 packets. I’m no math-wizard, but that seems to be about 5% of the traffic, in a very short time frame.

But the pic is awesome! Right?

20100908-Photo1308

One admin, multiple domains

So I want to be able to have a single Django admin site for more than one domain. After talking it over with Carson, he showed me what needed to be done. It’s really quite simple when you talk to someone knowledgeable, and go over it from beginning to end.

Django Setup

First, setup your sites in whatever way makes sense to you. I have created a folder at the root called /sites, within that folder I created a project for each of the sites I want to host, and named them for their registered domain names. Second, each site that you want to have show up under the main admin site must have a unique SITE_ID. Third, those sites must all be attached to the same database on the backend.

The last important bit is this, only enable the admin site in the urlconf of the site that should have it. Then just add your sites to the sites table in the admin interface, and assuming your apps are site-aware, you should be good to go.

Apache Vhost Setup

Now that you have all the Django stuff out of the way you just need to setup Apache, each domain with it’s own vhost. Most likely that’s how you already have it setup, so there may be very little if anything to do.

Problems I hit

Site matching query does not exist: Turns out I added my two sites, and deleted the example. This screwed up the SITE_ID in the database. So example.com is SITE_ID 1, and your subsequent sites are sequentially numbered after that. If you mess it up liked I did you will need to manually adjust those entries in the db. Use whatever method your backend db provides for updating those records.