Monday, February 11, 2013

Group Policy Preferences with Item-Level Targeting.... watch out for Distribution Groups

I've been using IFMEMBER.EXE (from an old Windows Server Resource Kit... not even sure which version) in my login scripts for a long time.  This handy but awkward command lets you test for a user's membership in a Security Group.  I won't go into details about it here because it's not the point.  The fact that it's awkward and login scripts are growing more and more dated is important to this post, however.  Most things that you used to do in login scripts can now be handled differently.  One of the last items still in my login scripts is assigning printers based on group membership.  The reasons we need to do this are simple: people in our office need to be connected only to those printers that are near them.

As a side note, I also like to automate printer disconnection; and have found/devised a scriptable command to do this, too.  It's handy for when a printer is retired or its name needs to change for some reason.

Today I needed to restrict certain mission-critical printers in a "production" area so that only a limited group of people could print to them.  Prior to today, these were "common" printers - everyone was connected to them.  Therefore, I needed to remove the existing printer connection from everyone except those people who still need to print to those printers.  No problem for me... I whipped out my login scripts and crafted a few additional lines using a combination of the lovely IFMEMBER.EXE command and my printer disconnect script.  I also worked into the code a few lines to connect anyone to those printers who should have them.  This is being prepared for when a new person moves into or out of that functional area... all I would have to do is change their group membership and they'd either get, or have deleted, all the right printers.

Today things weren't working properly, though.  In my script I tested a new security group "PRINTERS-ASSEMBLY" (which itself contained two other groups... this is an important nuance)  and mapped or deleted printers based on the value of the environment variable ERRORLEVEL (which is how IFMEMBER.EXE works).  But it wasn't working properly for one of my users.  She didn't have the printers she was supposed to have.  So I began troubleshooting.

I narrowed down the problem to the fact that IFMEMBER did not recognize her as being in that group.  I didn't test any other users yet, as she was the only person complaining.  I reviewed the scripts and became satisfied that there were no dumb errors there... they were coded properly.  IFMEMBER simply wasn't acknowledging that the user was a member of the group.

While researching IFMEMBER in order to give myself a refresher - again looking for something dumb I might have done - I came across several articles describing something called "Item-Level Targeting" in Windows Server 2008's Group Policy Preferences.  (Here's one of them).  I had looked at Preferences before, but I was unaware of ILT.  I configured some ILT-based preferences for the printers in question and even used the "remove" option so that people who didn't need the pritners would have them removed by this same setting.  Sweet!  But it still didn't work.  Fro some reason this user was not seen as a member of the group.

At this point I will describe how the user was a member of the group.  The new group was called PRINTERS-ASSEMBLY.  It contained, among other things, a group named CLERKS.  This user was a member of the CLERKS group.  Aha!  I jumped to the conclusion that neither IFMEMBER or ILT recognized members of sub-groups.  I even confirmed this (so I thought) by adding the user directly to the PRINTERS-ASSEMBLY group.  When I did, the IFMEMBER and ILT mechanisms worked fine.  I was prepared to call Microsoft to step through all this and find out if there was anything that could be done.  Thankfully one of my more AD-savvy admins took a look at it with me, and together (I'll take part of the credit) we identified the problem... Distribution Groups.  The sub-group that the user was a member of was a Distribution Group - not a Security Group.  We had never had a need to use that group as a Security Group - it was in existence strictly for use as a handy way to e-mail a handful of people at once.  When I added it to the PRINTERS-ASSEMBLY group I didn't stop to check to see what type of group it was... I just added it and rocked on.

After fiddling around for a little while, we arrived at a great solution that just might help someone else one day, so I will outline it here.  If your ILT (or IFMEMBER) isn't returning a group membership that you know is correct, check the group's type.  If it's a Distribution Group, neither of these mechanisms will report membership.  So what do you do?  Simple:
  1. Make note of the members (and any other special properties) of the Distribution Group and then delete it.
  2. Create a new Security Group using the same name.
  3. In Exchange, create a new Distribution List from an Existing Group, and then select the newly-create Security Group.  This will create a Distribution-Enabled Security Group.  With this new entity you can both e-mail to its members and check for group membership using ILT and IFMEMBER.
If I had been creating all the groups from scratch this wouldn't have been a problem.  It's only because I was utilizing existing groups (and didn't check their type before adding them to a new group).  But it was a real problem with a pretty specific solution.