Problem in creating Timer Job

Anoop picture Anoop · Jun 24, 2009 · Viewed 10.4k times · Source

I have created a site collection inside a web application with user A as a site collection adminstrator. I have added a link in site feature page. On click of that link I am trying to create a timer job.Below is the code executed on click of the link

//Allow unsafe updates.
 SPContext.Current.Web.AllowUnsafeUpdates = true;

//Get current web application.
SPWebApplication webApp = SPContext.Current.Site.WebApplication;

// Create new job.
ArchiveJob automaticArchiveJob = new ArchiveJob(scheduleDetails.scheduleName, webApp);

SPHourlySchedule hourlySchedule = new SPHourlySchedule();
hourlySchedule.BeginMinute = 0;
hourlySchedule.EndMinute = 1;
automaticArchiveJob.Schedule = hourlySchedule;

//Finally update archival job.
automaticArchiveJob.Update();

Now when I logged in with user A and click on that link on 'site settings' page, I get an security exception with message "Access Denied" at line automaticArchiveJob.Update(). But if I logged in with administrator user (I am also logged in to the machine using this user) and click on the link it successfully creates the job. Also I made user A member of WSS_ADMIN_WPG group but still getting the same problem. Is there any thing else that I need to do to resolve the problem.

Answer

Sean P. McDonough picture Sean P. McDonough · Jun 24, 2009

The "Access Denied" is expected behavior given what you're attempting to do. Allow me to explain.

When a timer job instance is created, it is persisted to the farm configuration database. Accessing this database for write purposes is a privileged operation; as a rule of thumb, only the farm service account (that is, the account under which OWSTIMER.EXE executes) or accounts that explicitly have the rights required to carry out such an operation on the config database (typically administrators) will succeed.

By default, attempting to instantiate a timer job from within the site collection context is going to fail. Attempting the operation in an elevated privilege block (via SPSecurity.RunWithElevatedPrivileges) is only going to result in the web application's application pool account context being used instead of the current user context; this only succeeds if the app pool account has rights to write to the farm configuration database. If this happens, it's typically because (a) the farm service account is being used in roles that it shouldn't be in (to run content web apps, for example), or (b) extra permissions have been granted to the application pool account. Both cases represent a deviation from a best-practices operating model.

Timer job instances are typically created at Feature activation time in Features scoped at either the Farm or WebApplication level. Why? Because those Features are normally activated by administrators from either the command line (assuming the admin also has rights in the farm config database) or from within Central Administration (where activation occurs through the farm service account -- guaranteed to have rights to the config database). When the Feature is activated and the SPFeatureReceiver's FeatureActivated method is called, it is safe (from a security perspective) to setup the timer job.

Solving your particular problem properly will involve turning the problem on its head a bit. Instead of trying to instantiate the timer job from within the site collection on demand, I'd recommend setting up the equivalent of a "sweep" timer job at the time your Feature is activated. Admittedly, this takes more planning and effort than what you're trying to do, but your current path is only going to work if security is somehow adjusted -- and that's not recommended.

When I was putting together my BLOB cache farm flush Feature (http://blobcachefarmflush.codeplex.com), I had to do much the same thing myself. You can see the specifics of how I worked through timer job creation in the FeatureReceiver class (BlobCacheFarmFlushSweepJobFeatureReceiver). The rest of the code and associated documentation may also help with some of the other challenges that come up.

Feel free to use what you find in any way; that's why it's there!

I hope that helps. If there are follow-up questions, fire away and I'll answer as best as I can :-)