As I mentioned in my last post, I always security trim SharePoint. A very common issue with a security trimmed SharePoint is the "access denied" message that you receive when trying to activate the "Office SharePoint Server Publishing Infrastructure" site collection feature.
There are lots of blog topics about this. Most refer to this one as the definitive source.
The issue here is that the publishing feature actually breaks a security rule. When you think about it, activating a site collection feature should only ever modify settings related to that site collection. I previously blogged about how it was bad practice for a site collection feature to modify the web.config files for a given web application.
If you set the scope of this feature at the site collection level, you are basically allowing a site collection administrator to make a change that affects all other site collections in the web application. Uh – does the site collection administrator have access to other site collections? Probably not, so why the hell would you allow them to perform a task that impacts on site collections to which they have no access? You don’t – it breaks the security model.
Well, as it happens, the publishing feature needs to create some SharePoint timer jobs to deal with the scheduling of publishing pages (i.e. Setting the date/time of when a page should be published to the masses). But where are timer jobs edited and managed?
Site Collection Administration! This is a *farm* level operation. Should a site collection administrator have the access rights to add custom timer jobs to the SharePoint farm? Hell, no! that is a farm administrator’s job!
So, is it no surprise then, that the publishing feature barfs when activated by a site collection administrator who has no *farm* level access? (I’ve pasted the error message to the end of this article).
I could whine about how this *should* be done, but instead, I’ll simply tell you the two quickest tricks to fix this issue. Both of these methods do not require changing permissions as per the aforementioned blog.
The first method, is to use STSADM to activate the feature for the site collection. By definition, to use the STSADM command, you have to be logged into the SharePoint server and be a farm administrator. Therefore, running the following command should do the trick.
stsadm -o activatefeature -name PublishingSite -url http://sitecollectionurl
The second method is the one that I use (although it’s less clean). As per normal, I create a web application, and then create a site collection. (Usually the blank template for reasons that I will talk about some other time). But rather than log into the site and activate the publishing feature via site settings, I immediately create a *second* site collection (e.g /sites/boo).
Remember that I am performing this task via SharePoint central administration, so I have farm level permissions.
When I create this second site collection, I choose the publishing site template. As the name suggests, the publishing site template uses the publishing site feature by default. So in creating this site collection, the SharePoint timer jobs get added to the farm.
I then immediately *delete* this site collection, as it is no longer needed.
Now I can load the originally created site collection and activate the publishing feature. It will work fine, because the timer jobs have already been created, and all of the other goodies that the publishing feature gives you, are scoped at the *site collection* level. Therefore, no more "access denied" messages.
Error message: (stop reading now – this is for google 🙂
"Feature Activation: Threw an exception, attempting to roll back. Feature ‘PublishingResources’ (ID: ‘aebc918d-b20f-4a11-a1db-9ed84d79c87e’). Exception: Microsoft.SharePoint.SPException: Provisioning did not succeed. Details: Failed to provision the scheduling job definitions. Page scheduling will not succeed. OriginalException: Access denied. —> System.Security.SecurityException: Access denied. at Microsoft.SharePoint.Administration.SPPersistedObject.Update() at Microsoft.SharePoint.Administration.SPJobDefinition.Update() at Microsoft.SharePoint.Administration.SPWorkItemJobDefinition.Update() at Microsoft.SharePoint.Publishing.Internal.RootProvisioner.<>c__DisplayClass5.<AddSchedulingJobDefinitions>b__4() at Microsoft.SharePoint.SPSecurity.CodeToRunElevatedWrapper