Microsoft

Blog Categories

Subscribe to RSS feed

Archives

SharePoint 2010: Calling SPPersistedObject.BaseUpdate() from a Content Web Application Results in “Access Denied”

SPPersistedObject is an important element in SharePoint 2010. It’s SharePoint’s main way of storing information across servers and acts as sort of the central brain of the application. Any data stored in it is guaranteed to be there in perpetuity. This makes SPPersistedObject a very useful class, but it’s not without its drawbacks. One of the most frustrating and least documented is the change that occurred in the class between SharePoint 2007 and 2010. Suppose you want to change this class, however slightly, via the UI by deploying a new expiration policy. This change will be prevented because of the addition of a security check on the ConfigurationDatabase object called DoesCurrentUserHaveWritePermission.

Such security is great because it keeps people with lower credentials from executing code in a higher security context, such as deploying a policy via a feature. Therefore, on the surface, this doesn’t appear to be a problem, especially if you’re running as the farm administrator, because that account obviously has access to the configuration database. However, that’s not the case when you’re interacting with SharePoint from the UI. The reason is because of a new property on the SPSecurity class called AdministrationAllowedInCurrentProcess.

This property obscurely derives its value from SPWebService.ContentService.RemoteAdministratorAccessDenied. Guess what, this value is always true for all web applications, even if the web application is running under the Farm Administrator account and you’re accessing it from the Farm Administrator account. This makes the AdministrationAllowedInCurrentProcess property false and DoesCurrentUserHaveWritePermission will also return false.

This results in a particularly nasty and misleading error message stating that: “The SPPersistedObject could not be updated because the current user is not a Farm Administrator”. This shows up in the Unified Logging Service (ULS) and an exception is thrown to the offending code with the message “Access Denied”. Both of these messages are lying. It’s not a question of access, it’s a question of procedure. You’re not supposed to be allowed to change an SPPersistedObject from the UI for content web applications.

 

 

Solutions

There are two solutions to this problem. One is more of a workaround and is not recommended. This is to set the RemoteAdministratorAccessDenied property to true for the web service in question from PowerShell with a little reflection. It’s literally four lines of code:

 1: [System.Reflection.Assembly]::LoadFile("C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14ISAPIMicrosoft.SharePoint.dll")
 2: $contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
 3: $contentService.RemoteAdministratorAccessDenied = $false
 4: $contentService.Update()

Keep in mind that this is not recommended for several reasons. First of all because RemoteAdministratorAccessDenied is used in other places and may have unknown side effects.

Use PowerShell

The accepted, and, I can’t say this enough, best way to accomplish updates to the SPPersistedObject class are to do whatever you need to do from PowerShell running as a Farm Administrator. This avoids the RemoteAdministratorAccessDenied check entirely because you’re interfacing with SharePoint directly instead of via the UI abstraction layer. Direct interaction avoids the security checks and instead DoesCurrentUserHaveWritePermission will return true because AdministrationAllowedInCurrentProcess will also return true because it’s always true from a PowerShell running under Farm Administrator credentials.

This is an instance where PowerShell is unsurpassed in its capabilities. The only downside is that the Farm Administrator must be involved in the process and this can’t be achieved by a standard user through a feature. I actually discovered this issue because I had an upgraded SharePoint 2007 policy feature that refused to deploy in SharePoint 2010. After some digging, I discovered this little undocumented gem. I hope this proves useful to you in your work. As always, drop any questions you have in the comments below and I’ll try to be as helpful as I can.

Tags: ,

Leave a Reply