views:

140

answers:

1

I have installed/configured Elmah on my personal SharePoint dev environment and everything works great since I'm logged in as admin, etc. I am using the MS Sql Server Error Log. (I am also using log4net to handle DEBUG/INFO/etc level logging and log statements are also stored in the db, in the same table as ELMAH's.)

However, on the actual dev server (not my personal environment), when I access http://example/elmah.axd I get the error "Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'". I understand that this is the traditional error for the "double-hop problem" but I don't even want my credentials to be passed along - I would just like the database access to be made with the credentials of the Application Pool Identity. When using the SP object model the SPSecurity.RunWithElevatedPrivileges is available; however, I do not want to modify the Elmah source.

My production environment precludes the use of SQL Server authentication, changing impersonation to false, or giving myself permissions on the db directly.

How can I get this to work? Am I missing something?

A: 

My production environment precludes the use of SQL Server authentication, changing impersonation to false, or giving myself permissions on the db directly.

Then you have no choice but to modify the Elmah source. Sorry.

This has less to do with the double hop problem and more to do with the poorly documented mechanism of impersonation in ASP.NET. According to this article, apparently <identity impersonate="true" /> causes ASP.NET to impersonate the default IIS anonymous account (IUSR_machinename). SharePoint needs this but it does you no good trying to access a remote database, so there is obviously something you need to do.

Yep, according to this article you must edit the Elmah source code and create a new class deriving from the abstract class ErrorLog. This new class then acts as a wrapper around the original SqlErrorLog class and runs its methods in a RWEP block. Here it is:

public class SqlErrorLogWEP : ErrorLog
{
    private SqlErrorLog sqlErrorLog;

    public SqlErrorLogWEP(IDictionary config)
    {
        sqlErrorLog = new SqlErrorLog(config);
    }

    public SqlErrorLogWEP(string connectionString)
    {
        sqlErrorLog = new SqlErrorLog(connectionString);
    }

    public override string Log(Error error)
    {
        string retVal = String.Empty;
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            retVal = sqlErrorLog.Log(error);
        });

        return retVal;
    }

    public override ErrorLogEntry GetError(string id)
    {
        ErrorLogEntry retVal = default(ErrorLogEntry);

        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            retVal = sqlErrorLog.GetError(id);
        });

        return retVal;
    }

    public override int GetErrors(int pageIndex, int pageSize, System.Collections.IList errorEntryList)
    {
        int retVal = -1;

        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            retVal = sqlErrorLog.GetErrors(pageIndex, pageSize, errorEntryList);
        });

        return retVal;
    }
}

It goes without saying that you will now need to reference SharePoint in the Elmah project and your Elmah.dll will need to be GACed. I've tested this myself and it works. Good luck.

Repo Man
I did end up editing the Elmah source - not as elegant as your solution though. I just wrapped the db calls in "RunWithElevatedPrivileges" and of course put the assembly in the GAC, etc. Thanks!
Chloraphil