R – Error on updating SPPersistedObject from web part

Securitysharepointweb-parts

I have written two features in SharePoint 2007.
One is scoped at Site level and it basically adds a web part to the site collection where it is activated. This feature assembly is deployed under the 'bin' directory.
Second is Farm scoped which is my custom SPPersistedObject and is deployed in Central Administration. The assembly is added to GAC.

From the web part I need to update my custom object. This is working fine in most cases. But on some servers that follow the least privilege administration domain accounts '
http://technet.microsoft.com/en-us/library/cc263445.aspx' I am getting the below error

System.Security.SecurityException:
Access denied. at
Microsoft.SharePoint.Administration.SPPersistedObject.Update()
at MyWebPart.<>c__DisplayClass1.b__0()
at
Microsoft.SharePoint.SPSecurity.CodeToRunElevatedWrapper(Object
state) at
Microsoft.SharePoint.SPSecurity.<>c__DisplayClass4.b__2()
at
Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated
secureCode) at
Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback
secureCode, Object param) at
Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated
secureCode) at
MyWebPart.RenderWebPart(HtmlTextWriter
writer) The Zone of the assembly that
failed was: MyComputer

Do I need to set any permissions or CAS policies to prevent this error?

Below is my current CAS policy set for the web part assembly. Do I need to make any changes here.

<CodeAccessSecurity>
    <PolicyItem>
      <PermissionSet class="NamedPermissionSet" version="1" Name="MyPermission" Description="Permission set for my solution">
        <IPermission class="System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Level="Medium"   />
        <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="AllFlags" />
        <IPermission class="Microsoft.SharePoint.Security.WebPartPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" Connections="true"  />
        <IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"  version="1" ObjectModel="true" UnsafeSaveOnGet="true" Impersonate="true"/>
        <IPermission class="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true">
          <ConnectAccess>
            <URI uri="$OriginHost$"/>
            <URI uri="http://.*\.xyz\.com/.*"/>
          </ConnectAccess>
        </IPermission>
      </PermissionSet>
      <Assemblies>
        <Assembly Name="MyWebPart" Version="1.0.0.0" PublicKeyBlob="0024000004800000940000000602000000240000525341310004000001000100df0e85cb8c660241cd3225eb653a590b91303ddbd37f8f1e661d2dffb840a258b899d6bacbbc55d03768d5ea0260ee4c8341fd447d7200abdb74b837733c3f756833e169cae803aef808530dd3ddad953a49492faee3eeba6f0dba66b0d66f1f9ca5266c69dcb799ed364db5e9e6ebcd4e81fb27365de962cbe6e7e7fba300dc"/>
      </Assemblies>
    </PolicyItem>
  </CodeAccessSecurity>

Please advice.

Regards,
Jagannath

Best Answer

Jagannath,

The problem you're encountering is due to the fact that the backing store for the data from SPPersistedObject-derived types is the SharePoint farm configuration database. In a least privileges installation, the only account that has anything other than read access to this database is the farm service (timer service) account. Even elevating privileges in your code is only going to "raise" your security context to that of the application pool account under which the site is running within IIS.

I've encountered the situation you're in before, and I'm only aware of two ways to work around it:

  1. Find a way to run your application code within the context of the farm service account. This normally translates to running the code as a custom timer job.

  2. Adjust the farm configuration database permissions to grant the application pool account (assumed when run as part of an elevated security block) write access.

Of these two options, only the first option stays true to the "least privileges" principle of execution ... but it does entail re-architecting your code.

I've generally had good creating a "sweep" custom timer job that gets created and scheduled to run at Feature activation time. That timer job then checks the site collection (typically sweeping an entire web application) to see if properties need to be persisted, updated, etc. If it finds updates are necessary, they are carried out by the timer job since it has the required access level.

An example of what I'm describing appears in a Feature I put out on CodePlex (http://blobcachefarmflush.codeplex.com/SourceControl/changeset/view/53851#797787). I needed to update the Properties bag on an SPWebApplication instance, and the only way to do so was from within the context of a timer job. When a user makes changes from within the UI, a flag gets set on Properties collection of the site collection's RootWeb. The timer job sweeps through the site collection, and when it sees such a flag set, it takes care of making the necessary changes from the appropriate security context.

I hope this helps!

Related Topic