Second Life of a Hungarian SharePoint Geek

July 6, 2013

Querying the SharePoint audit log for group membership changes of a specific user

Filed under: Audit log, PowerShell, SP 2010 — Tags: , , — Peter Holpar @ 21:10

Recently I had to filter the SharePoint audit log for membership changes of a specific user to answer the question, when the user has been added to / deleted from any groups and who has performed the action. I used the following PowerShell script to find the required information:

$site = Get-SPSite "http://yoursite.company.com"

$startDate = Get-Date "1/1/2013 7:00 AM"
$loginName = "domain\user"
$userId = $site.RootWeb.AllUsers | ? { $_.UserLogin -eq $loginName } | % { $_.ID }

function DumpEvents($site, $searchPattern, $startDate, $eventType, $eventName) { 
  $usersList = $site.RootWeb.SiteUserInfoList 

  $query = New-Object Microsoft.SharePoint.SPAuditQuery($site)
  $query.AddEventRestriction($eventType)
  $query.SetRangeStart($startDate)
  $result = $site.Audit.GetEntries($query) | ? { $_.EventData -like $searchPattern } | % {
   [xml]$eventData = "<eventData>" + $_.EventData + "</eventData>"
   $groupId = $eventData.SelectSingleNode("//groupid").InnerText 
   $groupName = $groupId 
   try { $groupName = $usersList.GetItemById($groupId).Name } catch { }
   $userName = $_.UserId
   try { $userName  = $usersList.GetItemById($_.UserId)["Name"] } catch { }
   Write-Host $eventName "Group" $groupName "on" $_.Occurred "by" $userName
  }
}

Write-Host Changes in group membership of $loginName since $startDate
Write-Host ————————————————–

$searchPattern = "*<user>$userId</user>*"
$eventType = [Microsoft.SharePoint.SPAuditEventType]::SecGroupMemberDel
DumpEvents $site $searchPattern $startDate $eventType "Deleted from"

Write-Host ————————————————–

$searchPattern = "*<userId>$userId</userId>*"
$eventType = [Microsoft.SharePoint.SPAuditEventType]::SecGroupMemberAdd
DumpEvents $site $searchPattern $startDate $eventType "Added to"

The EventData of the log entries contains the IDs of the affected users and groups. I try to resolve the user and group based on their ID (using the GetItemById method), however they might have been deleted since the change, so I included try blocks to be prepared for the possible exceptions.

Note 1: We cannot use the RestrictToUser method of the SPAuditQuery object to filter the results for the user affected by the change. The goal of this method is to filter the audit log entries for the user performed the action.

Note 2: the format of EventData is different at events SecGroupMemberAdd / SecGroupMemberDel. In the first case the userId node contains the user ID, whereas in the second case the same information can be found in the user node.

Note 3: If the change was initiated from a code block with impersonation / elevated permissions, the log entry contains the ID of the impersonated identity, and not the ID of the initiator user. That might be a problem if we need to track down the user who changed the group membership. In this case we should store the required information from the application in custom audit entries.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: