Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to find changes to Active Directory.
Hey, Scripting Guy! I have this problem. It seems our company has undergone a lot of changes recently, and I need to find what changes have impacted Active Directory. Basically, I do not even know where to start. I would like to get an overview of what things have changed since a specific date. Is this even possible with Windows PowerShell?
—GF
Hello GF,
Microsoft Scripting Guy, Ed Wilson, is here. Hey, the weekend is nearly here—at least if you live on the eastern coast of the United States. If you are in Australia, then the weekend is already underway. That is one thing I love about Australia, they always start the weekend early. Anyway, it should be a nice sunny weekend around here, and there are outdoor concerts planned. It should be a great time to get out and have some fun.
So GF, I will help you out so maybe you can get out of the office and enjoy some nice sunny outdoor weather.
Two things are required to find when things changed. The first thing you need to find when things changed is a date. This becomes your point of departure. If you were looking for a ship, it would be your datum. As it is, you don’t really know what you are looking for, so you need to create a DateTime object.
The easiest way to do this is to use the [datetime] type accelerator to convert a string into a DateTime object for you. I can supply the date in a format that my local input will accept, so for me that becomes month, day, year.
Here is the command I use to create a DateTime object that I will use as my beginning point of search. (By the way, I am not going to give a time, so the time will begin at midnight.)
$dte = [datetime]"1/1/2015"
As you can see here, I have created a DateTime object for January 1, 2015 (which was a Thursday):
PS C:\> $dte
Thursday, January 1, 2015 12:00:00 AM
Now I need to find all objects in Active Directory that have a WhenChanged property (attribute) that is greater than January 1, 2001 at midnight. Because GF only says he is interested in knowing the numbers of the different types of objects that changed, I pipe the output to the Group-Object cmdlet.
To be able to know what types of objects are changed, I will need the ObjectClass property. To find objects in Active Directory, I use the Get-ADObject cmdlet. My filter uses the WhenChanged property and I specify my DateTime object that I stored in the $dte variable. Here is the command I use:
Get-ADObject -Filter 'whenchanged -gt $dte' | Group-Object objectclass
And here is an example of the type of output that arrives:
PS C:\> Get-ADObject -Filter 'whenchanged -gt $dte' | Group-Object objectclass
Count Name Group
----- ---- -----
1 domainDNS {DC=NWTraders,DC=com}
1 groupPolicyContainer {CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,...
1257 user {CN=Administrator,CN=Users,DC=NWTraders,DC=com, CN=Kim ...
1 group {CN=Remote Desktop Users,CN=Builtin,DC=NWTraders,DC=com}
6 computer {CN=DC1,OU=Domain Controllers,DC=NWTraders,DC=com, CN=S...
1 rIDManager {CN=RID Manager$,CN=System,DC=NWTraders,DC=com}
1 rIDSet {CN=RID Set,CN=DC1,OU=Domain Controllers,DC=NWTraders,D...
2 serviceConnectionPoint {CN=Windows Virtual Machine,CN=SGW,CN=Computers,DC=NWTr...
1 rRASAdministrationConn... {CN=RouterIdentity,CN=SGW,CN=Computers,DC=NWTraders,DC=...
2 organizationalUnit {OU=dataImport,DC=NWTraders,DC=com, OU=Charlotte,DC=NWT...
What does this output tell me? Well, it tells me that something changed in DNS, Group Policy, groups, computers, organizational units, and on and on. What I do not know is what changed.
Was an organizational unit (or two) created or merely modified? The 1257 users could be new users or changed users. When a user changes the password (which hopefully would have happened a few times since January 1, 2015), the user object changes. The same thing for the six computer objects—they have passwords that automatically change.
If you are looking for when things were created, well, guess what? There is also a WhenCreated property (attribute). I can modify my code a little bit to see what objects were created after a specific date. This time, I will change my date to show objects that were created since July 1, 2015. The output is shown here:
PS C:\> $dte = [datetime]"7/1/15"
PS C:\> $dte
Wednesday, July 1, 2015 12:00:00 AM
PS C:\> Get-ADObject -Filter 'whencreated -gt $dte' | Group-Object objectclass
Count Name Group
----- ---- -----
1 organizationalUnit {OU=Charlotte,DC=NWTraders,DC=com}
So, only one object has been created in Active Directory since July 1, 2015. And because there is only one object, it shows up in the Group property from Group-Object. It is the Charlotte organizational unit. If there were more than one object, I might not be able to see the group details. So I would remove the Group-Object command. Here is the output:
PS C:\> Get-ADObject -Filter 'whencreated -gt $dte'
DistinguishedName Name ObjectClass ObjectGUID
----------------- ---- ----------- ----------
OU=Charlotte,DC=NWT... Charlotte organizationalUnit f53f519c-c548-401a...
If I want to see all of the properties (attributes) from the newly created object, I specify the –properties parameter and use the asterisk wildcard character ( * ) to select all of the properties. This command is shown here with the associated output from the command:
PS C:\> Get-ADObject -Filter 'whencreated -gt $dte' -Properties *
CanonicalName : NWTraders.com/Charlotte
CN :
Created : 7/2/2015 9:47:53 AM
createTimeStamp : 7/2/2015 9:47:53 AM
Deleted :
Description : Charlotte office users
DisplayName :
DistinguishedName : OU=Charlotte,DC=NWTraders,DC=com
dSCorePropagationData : {12/31/1600 7:00:00 PM}
instanceType : 4
isDeleted :
LastKnownParent :
Modified : 7/2/2015 9:47:53 AM
modifyTimeStamp : 7/2/2015 9:47:53 AM
Name : Charlotte
nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity
ObjectCategory : CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=NWT
raders,DC=com
ObjectClass : organizationalUnit
ObjectGUID : f53f519c-c548-401a-982d-bd9f38b20d97
ou : {Charlotte}
ProtectedFromAccidentalDeletion : False
sDRightsEffective : 15
uSNChanged : 430200
uSNCreated : 430200
whenChanged : 7/2/2015 9:47:53 AM
whenCreated : 7/2/2015 9:47:53 AM
What does not appear here is who created the object. To find this information, I would need to enable auditing for the creation of Active Directory objects. For me, that is pretty much a one-off scenario, so I would use the GUI tools to do that, and I would not use Windows PowerShell to turn on auditing.
GF, that is all there is to using Windows PowerShell to find changes to Active Directory. This also concludes Active Directory Week. Join me tomorrow when I will have a way cool guest blog post.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy