In my recent post I’ve already illustrated how to read and set the primary and secondary site collection administrators (the Owner and SecondaryContact properties of the corresponding SPSite object) via PowerShell. In that samples I’ve used elevated privileges to achieve my goals.
Let’s see if it is there a way without elevating the privileges.
Before PowerShell, before SharePoint 2010, the standard way to display / change the site owner and the secondary owner in command line was the stsadm command, that is still available to us.
For example, we can display this information for all site of a web application using the enumsites operation:
stsadm -o enumsites -url http://mysiteroot
To set the site owner, we can use the siteowner operation with the ownerlogin parameter:
stsadm -o siteowner -url http://mysiteroot/users/user1 -ownerlogin "domain\user1"
For the secondary admin, use the secondarylogin parameter instead of ownerlogin.
Note: You should have local administrator rights on the server where you run this commands, otherwise you receive an “Access denied.” error message. The reason, that for most of the stsadm operation, the following security check is performed in the entry method (public static int Main) of the Microsoft.SharePoint.StsAdmin.SPStsAdmin class:
if (!SPAdministrationServiceUtilities.IsCurrentUserMachineAdmin())
{
Console.WriteLine(SPResource.GetString("AccessDenied", new object[0]));
Console.WriteLine();
return -2147024891;
}
I decided to check, what kind of method stsadm uses to read and change the values. The implementation of the siteowner operation can be found in the Microsoft.SharePoint.StsAdmin.SPSiteOwner class. To access the the Owner and SecondaryContact properties of the SPSite object, the OwnerLoginName and SecondaryContactLoginName properties of the SPSiteAdministration class are used. In the constructor of this class there is a security check that verify if the calling user is a farm administrator:
internal SPSiteAdministration(SPSite site)
{
if (site == null)
{
throw new ArgumentNullException("site");
}
this.m_Site = site;
if (this.m_Site.WebApplication.Farm.CurrentUserIsAdministrator())
{
this.m_Site.AdministratorOperationMode = true;
}
…
To display the owner and the secondary contact of the site collection, we can use the following PowerShell script:
$url = "http://mysiteroot/users/user1"
$siteAdmin = New-Object Microsoft.SharePoint.Administration.SPSiteAdministration($url)
$siteAdmin.OwnerLoginName
$siteAdmin.SecondaryContactLoginName
Changing these values is so simple as:
$url = "http://mysiteroot/users/user1"
$siteAdmin = New-Object Microsoft.SharePoint.Administration.SPSiteAdministration($url)
$siteAdmin.OwnerLoginName = "domain\user1"
$siteAdmin.SecondaryContactLoginName = "domain\user2"
Note, that we are using the login name as string, and not an SPUser when assigning the values, and there is no need for elevated privileges. The caller must be a farm administrator for the current SharePoint farm, however, as we call this code directly, and not from stsadm, where this is checked, the user should not be a local admin.
I found it a bit inconsistent and disturbing, that we can access (read / set) the same properties via various objects and methods of the base SharePoint library, that perform various permission checks, and so one can avoid the security checks implemented in one of the objects when accessing the very same information via another class.
