We recently had a security requirement come down the line that required me to leave the wading pool of GPO administration behind and dive into the stormy waters of Powershell scripting. I am not going to dive into a full explanation of how to get started on powershell. What I am going to do is present my specific use-case as I ended up having to piece together a script from several different sources… Here we go…
So Client A comes to me and says… hey, you need to automate the disabling of contractor accounts that are older than 90 days. I said great, I will use a GPO and get on with my life. No such love, a GPO can’t do this. Time to dive into powershell.
After lots of google searches I found several scripts that would allow me disable accounts that haven’t been USED in X number of days. This isn’t what I needed, I needed a script that would disable accounts that were older than 90 days. So first, a bit of active directory administration had to be done.
- We had to identify those contractor accounts.
- We had to create a sub organizational unit off of our main user accounts organizational unit and draft, publish, and implement a policy that all contractor accounts be placed in this OU.
- I had to create a powershell script that would later get run as a scheduled task on a domain controller to search this OU and do the disabling.
- What about accounts that were purposefully re-enabled? I don’t want the script to bother with those for another 90 days… That had to be part of the search function as well.
Here is what I ended up with after a good bit of reading and putting the pieces together from around the web (some information modified for security, syntax left intact).
Okay, let’s break this thing down a bit… When this script is run it starts with the Get-ADUser commandlet which among other things clarifies that all we care about are user accounts, not computer or other accounts.
-Filter – This tells us that we want to pull more than one user account, based on a filter… In this case, all user accounts due to the “*”.
-SearchBase – This is important in my use-case. I wanted to focus on a specific OU in our active directory infrastructure. This is specified here using relatively common LDAP syntax.
-Properties – This is supremely important for this operation… You have to declare some object attributes on the user accounts that aren’t pull in by default by the “Get-ADUser” commandlet… namely, whenCreated and whenChanged (both of which I hope are self-explanatory).
Okay, so “Get-ADUser” has been told to pull in all accounts in this OU and to additionally pull those two specified properties for each account.
Next we pipe that output into an additional commandlet which will work with those properties to further narrow down our list of users. “Where-Object”
You can read up on Where-Object syntax below (and after doing so myself I realized my above code could probably be condensed using an “and” statement rather than piping to another where-object commandlet but for the sake of me getting this article written I won’t go there for now).
Using the Where-Object commandlet I started out by narrowing down based on that “whenCreated” property we pulled in earlier. I used the “-le” = less than or equal to (which I will get to in a moment) then tack on the “get-date” commandlet that pulls today’s date. Now the syntax is a bit confusing at first glance here as the “AddDays” modifier actually can go either way and in this case is being used to subtract days. Because we have specified “-90” instead of just “90” we are going to be subtracting that number of days from today’s date. You can test all of this out from any powershell command line by running the following commands:
(Get-Date).AddDays(2)
And observe the results to get an idea of how the syntax works.
In my use case then, The whole part of the command specifying (Get-Date).AddDays(-90) will actually output a date 90 days in the past from the day the command is run.
Back to the bit about “le” – The “Where-object” commandlet lets you do some basic mathematical functions. In this case we are using the logical operator “less than or equal to”. So reading the above command we are specifying “less than or equal to” 90 days ago. where “less” would be farther back into the past. Conversely, if you wanted to pull accounts created WITHIN the last 90 days you could use the “-ge” operator which is greater than or equal to. This is what I found in use most commonly when trying to locate newly created accounts. If you are interested in that, see the references below.
Next, I piped the output of this filter to another “where-object” commandlet to further narrow my search down to accounts that were last modified more than 90 days ago as well. This way if a Domain Admin goes in and re-enables an account that was created more than 90 days ago it won’t get disabled again the next time the script is run. This effectively resets the 90 day timer ever time the account is re-enabled. I won’t dive into the syntax again as the logic is pretty much the same.
Last but not least, a final pipe of our resulting output to the “disable-ADaccount” commandlet which will disable any of the accounts in that OU that made the cut.
Okay, I hope you don’t feel like you just took a drink from a fire hydrant (I am sure anyone more experienced with powershell is probably chuckling that I would find this to be somewhat complex…). I had a hard time finding exactly what I needed so here it is if you find yourself in a similar position.
Cheers!
References:
Get-ADUser commandlet help:
http://technet.microsoft.com/en-us/library/ee617241.aspx
Where-Object commandlet help:
http://technet.microsoft.com/en-us/library/ee177028.aspx
Powershell Script for Disabling Inactive Computer Accounts:
http://community.spiceworks.com/scripts/show/1861-find-and-disable-or-remove-inactive-ad-computer-accounts
Powershell – Find newly created User accounts
http://community.spiceworks.com/topic/387016-how-do-i-find-newly-added-users-to-active-directory-with-powershell