Scripting based off changes in AD

lsud00dlsud00d Member Posts: 1,571
Has anyone done anything fancy (or simple!), using changes in AD as the trigger?

I am trying to automate shadow group membership (as if shadow group membership isn't automated enough). I've enabled auditing on the event I want (user add or move OU's) and will write a posh script to watch event viewer for those events, extract the OU where the event occurred, which will then kick off the shadow group script to enact on that OU.

This is essentially a way to automate access to mapped drives/printers when users move OU's since the AD environment I'm currently in has mobile users and a functional (vs. geographic) ADUC design.

I'm leaning towards having the posh script that's watching event viewer run every 10-15 minutes, then if there's a hit kick off the shadow group function. I was looking into the FileSystemWatcher .NET class to avoid a scheduled task or sleepy script, but that still requires a file/dir update which is not specific enough for AD purposes.

Any ideas?


  • QordQord Senior Member Member Posts: 632 ■■■■□□□□□□
    Is this your only reason for turning on auditing? If so, you might be just as well off disabling auditing and instead assigning the membersof to a variable (or overwriting to a text file) that can be compared at a later time.

    E: To answer your initial question, I haven't found anything great for monitoring AD changes and using them to trigger other changes. Auditing is out of the question for us, so I'm stuck comparing memberships at time intervals, and acting on changes found there.
  • lsud00dlsud00d Member Posts: 1,571
    I'm awaiting an answer on if auditing is already enabled in this environment. If not, my backup was a method similar to yours...just store them in a variable, do a compare, and look to see if there are any side indicators.

    With auditing I can assign a task to trigger on event, and if the further conditions are met (beyond just eventID), then the script will be executed on that OU, so essentially achieve full automation.

    Here's what I have of the script so far:

    get-eventlog security -instanceid 4662 | ? {$_.message -like "*%%7685*} | select @{n='Message';e={$_.ReplacementStrings[6]}}

    The eventID and message excerpt grab the event I'm looking for (moving a user between OU's). Sorting out the info from there took some research but you can array the message section (it's one big object) via replacement strings, then the GUID of the CN I want (where the user moved to) is item 7, or index 6.

    Now I'm running into an issue of converting the GUID to ldap username to do a lookup and extract the OU where the shadow group membership portion of the script can finally run.


    1. Auditing is in place
    2. I'm a dummy, get-adobject accepts GUID's as input. TIL.
  • lsud00dlsud00d Member Posts: 1,571
    So I finished the bulk of the script, it all fell into place once I was able to convert GUID to LDAP name. I had a HUZZAH/bang head moment forsure.
    #gets the user GUID based on moving OU's
    $userguid = Get-Eventlog security -instanceid 4662 | ? {$_.message -like "*%%7685*"} | select @{n='Message';e={$_.ReplacementStrings[6]}}

    #gets the user DN
    $usercn = get-adobject $userguid | select -expand distinguishedname

    #extracts the OU from DN
    $userou = ([adsi]"LDAP://$usercn").parent -replace "LDAP://"

    #Shadow groups script to query users in OU then update group membership of that AD group
    dsquery user "$userou" | dsmod group $usergroup -chmbr

    The shadow groups will be defined somewhere, either statically in the script or in one of the group attributes (which would be queried to grab the right group).

    I should hopefully finish up testing on Monday. This is a pretty cool way to do something that other directory products (like Novell) can do inherently... ::shakes fist at Microsoft::
  • lsud00dlsud00d Member Posts: 1,571
    So after further diving into this, I realized it's not realistic to automate this by attaching it to a security event. There are an inordinate amount of 4662 event's generated for simply enabling the 'Create User' AD auditing and having this script fire off each time could potentially crash the machine. Even though it's runtime is fast, it can't keep up with 10+ events generated within a second.

    But, it does work well as a scheduled task/standalone script. In addition, I expanded the script because eventId 4662 and the 'write object' property (%%7685) are not specific enough for what I was looking for: a user moving OU's.

    I added this to the beginning, the comments help explain the third unique property I identified in the event logs that distinguish a user moving OU's from everything else of 4662 & %%7685
    # Finds the most recent event related to a user added to an OU (includes moves)# InstanceID specifies the correct event, 4662
    # Message "7685" means "Write Property"
    # ReplacementStrings[12] distinguishes this event from others since the 'Additional Info' data fields contains user information (and not a dash which this search uses to not select irrelevant results)
    # Finally the most recent index is selected since this is the event we want to act upon
    $result = get-eventlog security -instanceid 4662 -message "*%%7685*" | select index,@{n='Message';e={$_.ReplacementStrings[12]}} | ? {$_.Message -ne "-"} | select -expand index -first 1

    # Location of file to hold $result value (persistence)
    $loc = "c:\scripts\ouchangeresult.txt"

    # Compare most recent result to result in file. If different, continue on with the script
    if ($result -eq (cat $loc)) {
    write-host `n"No user OU changes found in Event Viewer Security log--Exiting script"`n -fore green; sleep 1
    Else {
    write "Continuing script"

    # Write the new result to a file
    $result | out-file "$loc"

    Note that I use 'write-hosts' just for visual confirmation when composing scripts. I normally comment them out/remove them when put into production, unless I intend to run them manually.

    My new method is similar but the username is passed as an argument and the other information is parsed from there. I stamp the Shadow Groups 'Homepage' extended attributed with the OU it represents and use this to locate the appropriate Shadow Group based upon the users OU
    $shadowgroup = get-adgroup -searchbase "OU=Shadow Groups,OU=Groups,DC=demo,DC=local" -filter {Homepage -like $userou} | select -expand distinguishedname

    HTH someone either on here or Googles this at some point...I couldn't find anything similar to what I was trying to achieve. Learned a LOT about event viewer/XML querying/filtering though.
Sign In or Register to comment.