rj_mathis@sbcglobal.net

Author



.

I’ve talked on several occasions about how we can easily use the SharePoint 2010 object model (OM) to learn who has access to a securable object (SPWeb, SPList, or SPListItem) and the fact that we can use the same mechanisms within PowerShell to make useful security/audit reports. On some of those occasions I’ve shown a version of a PowerShell speech which gives you a dump to the screen or a text file of every securable object and who has access to it and how they were given access to it – now I’d like to share a new version of that speech.

Before we get to the actual speech let’s first talk about how to get the information. All securable objects have a method named GetUserEffectivePermissionInfo which is defined in the abstract base class SPSecurableObject (in 2007 this method was defined directly on the SPWeb, SPList, and SPListItem objects). This method income back an SPPermissionInfo object which we can use to inspect the various role classification bindings and corresponding permission levels.

Once we have the permission details we simple loop through the SPRoleAssignments objects via the RoleAssignments property. This will give us information about how the user is given access to the store. Next we look at the RoleDefinitionBindings property which income back a collection of SPRoleDefinition objects that tell us about the type of access granted (e.g., Full Control, etc.).

I then take all this information, stick it in a hash table which I then use to make a new object which gets written to the pipeline.

So with that, let’s take a look at the code:

function Get-SPUserEffectivePermissions([object[]]$users, [Microsoft.SharePoint.SPSecurableObject]$InputObject) {
   
start { }
   
process {
       
if ($_ -isnot [Microsoft.SharePoint.SPSecurableObject]) {
           
throw A valid SPWeb, SPList, or SPListItem must be provided.
        }
       
$so = $_
       
foreach ($user in $users) {
           
# Set the users login name
           $loginName = $user
           
if ($user -is [Microsoft.SharePoint.SPUser] -or $user -is [PSCustomObject]) {
               
$loginName = $user.LoginName
            }
           
if ($loginName -eq $null) {
               
throw The provided user is null or empty. Specify a valid SPUser object or login name.
            }
           
           
# Get the users permission details.
           $permInfo = $so.GetUserEffectivePermissionInfo($loginName)
           
           
# Determine the URL to the securable object being evaluated
           $store = $null
           
if ($so -is [Microsoft.SharePoint.SPWeb]) {
               
$store = $so.Url
            }
elseif ($so -is [Microsoft.SharePoint.SPList]) {
               
$store = $so.ParentWeb.Site.MakeFullUrl($so.RootFolder.ServerRelativeUrl)
            }
elseif ($so -is [Microsoft.SharePoint.SPListItem]) {
               
$store = $so.ParentList.ParentWeb.Site.MakeFullUrl($so.Url)
            }

            # Get the role assignments and iterate through them
           $roleAssignments = $permInfo.RoleAssignments
           
if ($roleAssignments.Count -gt 0) {
               
foreach ($roleAssignment in $roleAssignments) {
                   
$member = $roleAssignment.Member
                   
                   
# Build a string array of all the permission level names
                   $permName = @()
                   
foreach ($classification in $roleAssignment.RoleDefinitionBindings) {
                       
$permName += $classification.Name
                    }
                   
                   
# Determine how the users permissions were assigned
                   $assignment = Direct Assignment
                   
if ($member -is [Microsoft.SharePoint.SPGroup]) {
                       
$assignment = $member.Name
                    }
else {
                       
if ($member.IsDomainGroup -and ($member.LoginName -ne $loginName)) {
                           
$assignment = $member.LoginName
                        }
                    }
                   
                   
# Make a hash table with all the data
                   $hash = @{
                        Store
= $store
                       
Store Type = $so.GetType().Name
                        User
= $loginName
                        Permission
= $permName -join ,
                       
Granted By = $assignment
                    }
                   
                   
# Exchange the hash to an object and productivity to the pipeline
                   New-Object PSObject -Property $hash
                }
            }
        }
    }
   
end {}
}

Fantastic – we’ve got the code – so now you’re probably asking, “how the heck do I use it?” Well the first thing you need to do is save it to a file, let’s call it SecurityReport.ps1 and we’ll place it in the root of the C drive. Once saved we can load it in reminiscence by the following:

Now for the fun stuff :) . The examples I’m going to show will build off of each other and will eventually conclude with an example that gives me a report for all users and all securable objects throughout the entire farm. The first example I want to show is how to retrieve a report for a single user and a single web (we’ll reuse the $user variable throughout the speech so I’ll only define it once here):

$user = "sp2010\siteowner2"
Get-SPWeb http://portal | Get-SPUserEffectivePermissions $user | Out-GridView -Title "Web Permissions for $user"

Running this command will generate a grid view as shown here:

image

Note that I may possibly have just as easily saved the consequences to a CSV file which I may possibly then open in Excel by the Export-Csv cmdlet:

Get-SPWeb http://portal | Get-SPUserEffectivePermissions $user | Export-Csv -NoTypeInformation -Path c:\perms.csv

For this next example I’m going to show the permissions for the same user for ALL webs throughout the entire farm (note that this won’t include lists or items):

Get-SPSite -Limit All | Get-SPWeb | Get-SPUserEffectivePermissions $user | Out-GridView -Title "All Web Permissions for $user"

Now I want to get the permissions for the same user for all lists throughout the entire farm:

Get-SPSite -Limit All | Get-SPWeb | %{$_.Lists | Get-SPUserEffectivePermissions $user} | Out-GridView -Title "List Permissions for $user"

Now we’re going to get nice and deep and show the permissions for every single item throughout the entire farm (probably don’t want to run this on any front-end servers):

Get-SPSite -Limit All | Get-SPWeb | %{$_.Lists | %{$_.Items | Get-SPUserEffectivePermissions $user}} | Out-GridView -Title "Item Permissions for $user"

So now that I’ve shown you how to get the individual securable objects consequences throughout the farm for a single user let’s now go ahead and stitch them together into one report:

Get-SPSite -Limit All | ForEach-Object {
    $site = $_
    $webPermissions += $site | Get-SPWeb | Get-SPUserEffectivePermissions $user
    $listPermissions += $site | Get-SPWeb | %{$_.Lists | Get-SPUserEffectivePermissions $user}
    $itemPermissions += $site | Get-SPWeb | %{$_.Lists | %{$_.Items | Get-SPUserEffectivePermissions $user}}
    $site.Dispose();
}
$webPermissions + $listPermissions + $itemPermissions | Out-GridView -Title "Web, List, and Item Permissions for $user"

In this example I’m austerely performing the same calls but appending to an array of objects and then dumping the amalgamation of those arrays to the grid. Note that in this case I’m calling $site.Dispose() but not more than I’ll be by the SPAssignmentCollection to dispose of objects – keep reading for an explanation.

So now lets take it one step further and see how we can get the same reports but this time for every user. We’ll start with webs again – in this example we’ll get the permissions for all users for a given site:

$gc = Start-SPAssignment
$site = $gc | Get-SPSite http://portal
$site | Get-SPWeb | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName) | Out-GridView -Title "Web Permissions for All Users In $($site.Url)"
$gc | Stop-SPAssignment

As you can see I’m basically by the SiteUsers property from the root web and passing the login name for each user into the function. Note that here I’m by the Start-SPAssignment and Stop-SPAssignment cmdlets – that’s because I’m by the SPSite object after the pipeline execution finishes (as opposed to the above) so I need to make sure it gets disposed (I may possibly just as easily called Dispose on the object as I did above but I’m attempting to demonstrate when/why you’d use the assignment collections).

Now lets see the lists:

$gc = Start-SPAssignment
$site = $gc | Get-SPSite http://portal
$site | Get-SPWeb | %{$_.Lists | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)} | Out-GridView -Title "List Permissions for All Users in $($site.Url)"
$gc | Stop-SPAssignment

Starting to see a pattern? Let’s take a look at the list items now:

$gc = Start-SPAssignment
$site = $gc | Get-SPSite http://portal
$site | Get-SPWeb | %{$_.Lists | %{$_.Items | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)}} | Out-GridView -Title "Item Permissions for All Users in $($site.Url)"
$gc | Stop-SPAssignment

Fantastic! So now lets piece this last bit together so we can see the permissions for all webs, lists, and list items for every user within a single site collection:

$gc = Start-SPAssignment
$site = $gc | Get-SPSite http://portal
$webPermissions = $site | Get-SPWeb | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)
$listPermissions = $site | Get-SPWeb | %{$_.Lists | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)}
$itemPermissions = $site | Get-SPWeb | %{$_.Lists | %{$_.Items | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)}}
$webPermissions + $listPermissions + $itemPermissions Out-GridView -Title "Web, List, and Item Permissions for All Users in $($site.Url)"
$gc | Stop-SPAssignment

Alright, we’re nearly done – let’s now stitch this all together and generate a single report showing all permissions for all securable objects (webs, lists, and list items) for every user within every site collection:

Get-SPSite -Limit All | ForEach-Object {
    $site = $_
    $webPermissions += $site | Get-SPWeb | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)
    $listPermissions += $site | Get-SPWeb | %{$_.Lists | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)}
    $itemPermissions += $site | Get-SPWeb | %{$_.Lists | %{$_.Items | Get-SPUserEffectivePermissions ($site.RootWeb.SiteUsers | select LoginName)}}
    $site.Dispose();
}
$webPermissions + $listPermissions + $itemPermissions | Out-GridView -Title "Web, List, and Item Permissions for All Users in All Sites"

Note in this last example, as I did previously when looping through all site collections, I’m calling the Dispose() method inside the ForEach-Object speech block. I do this because objects wouldn’t otherwise get disposed in anticipation of the pipeline execution has finished and because it’s continuing to iterate so the pipeline has not yet completed. If I used the assignment collection I wouldn’t get a disposal in anticipation of after I’m done iterating which would be too late – I want to dispose right when I’m done with the individual SPSite objects to avoid out of reminiscence errors.

Reporting on who has access to what is one of the things I get questioned about most frequently so hopefully this code sample and corresponding examples will prove to be useful to people. One possible area of improvement to the speech would be to accommodate groups being passed in – right now I’m only considering users; and of course you may possibly easily turn the example usages into functions. As always, if anyone has any feedback (bugs, improvements, etc.) delight post here so that myself and others may benefit.

Check it out:SharePoint Automation

rj_mathis@sbcglobal.net

Tagged with: 2010accessDiscoveringObjectsSecurableSharePoint 

.

I have lots of emails that I’d like to archive to clean up “my folders” is there a way to copy these to my hard drive so I can delete from yahoo mail?

Best answer:

Answer by Jared!
Forward them to Gmail. Gmail has an Archive feature built in so that you never have to delete any messages, yet they don’t clog up your folders.

Add your own answer in the comments!

rj_mathis@sbcglobal.net

Tagged with: Archivalcopydriveemailfoldershardmessagespurposes 

Answers Rating

  • Big Cat on the Block: Get rid of the bum !! Who knows whether he’s been the pitcher or the...  Thumb up 0
  • Preetiranjan: I suggest you to cry more than more . You will see after cry you should much strong...  Thumb up 0
  • m_cyberfriend: I really don’t understand why you think so sad on knowing person’s...  Thumb up 0
  • Loren E: Hi, You are doing a very good job of keeping your computer safe. You have anti virus and...  Thumb up 0
  • Tom Jones: wow that sucks get rid of him/her  Thumb up 0
© 2010 Computersplace.net