Hi All,

Here's some sample code to illustrate how impersonation could easily be
added to the appender classes.  The goal would be to let the application
that consumes log4net be able to handle the impersonation when needed.
The sample's I'm including use an attribute called
ImpersonationFactoryAttribute that log4net can check for on the user's
DLL to let that DLL override the factory that supplies objects which do
the impersonation.

Here's how this would work.

1)  User adds this attribute to their DLL in the AssemblyInfo.cs file,
and specify the type of factory to read from their own DLL

[assembly:
log4net.Appender.Impersonation.ImpersonationFactoryAttribute(Impersonati
onFactoryType=typeof(LoggingTestApp.MyImpersonationFactory))]

2)  In the user DLL, the factory class would look something like this

        public class MyImpersonationFactory : IImpersonationFactory
        {
                public IExternalCredential
Create(log4net.Appender.IAppender appender)
                {
                        if( appender is
log4net.Appender.RollingFileAppender  || appender is
log4net.Appender.FileAppender )
                        {
                                return new MyImpersonator();
                        }
                        return null;
                }
        }

3)  The appender would add code to instantiate the IExternalCredential
object to use for impersonation.  For example, in RollingFileAppender

                override public void ActivateOptions() 
                {
                        this.credential =
Impersonation.ImpersonationFactory.Instance.Create( this );

                        ...
                }

4)  The appender would impersonate around operations that access system
resources.  For example, when the RollingFileAppender tries to delete a
file:

                protected void RollFile(string fromFile, string toFile) 
                {
                        ...

                        LogLog.Debug("RollingFileAppender: Deleting
existing target file ["+target+"]");
                        try
                        {
                                this.credential.Impersonate();
                                target.Delete();
                        }
                        finally
                        {
                                this.credential.Revert();
                        }

                        ...
                }

This is the basic mechanism, and you can see how easy this is both from
the external DLL that consumes log4net to extend, as well as how simple
it is for log4net to support.

Note the above code is using a NullImpersonation class, which has empty
Impersonate and Revert methods, allowing us to eliminate null checks for
better readability.  Alternatively, we could make the code add the null
check guard clauses, in which case the appender code above would change
to this:

                protected void RollFile(string fromFile, string toFile) 
                {
                        ...

                        LogLog.Debug("RollingFileAppender: Deleting
existing target file ["+target+"]");
                        try
                        {
                                if( null != this.credential )
this.credential.Impersonate();
                                target.Delete();
                        }
                        finally
                        {
                                if( null != this.credential )
this.credential.Revert();
                        }

                        ...
                }

What do you all think of this approach?  

This seems like a clean way to let external code handle the
impersonation.  For example, we would like this capability so we can
impersonate as a single user for file I/O operations, thus allowing us
to simplify our deployments for an ASP.NET application.  Currently, any
site user must have full permissions in the log directory.  A change
like this to the appenders would allow us to increase security and
simplify management of the logging folder by impersonating as a single
user.

Can we go ahead with adding this into the project?  If this approach
seems sound, the files I've attached can be added to CVS first, then
once added, the next stage of work in the appenders could begin,
changing the resource access to account for the impersonation calls.

I appreciate your feedback and consideration!

-Doug

Attachment: ImpersonationFactory.cs
Description: ImpersonationFactory.cs

Attachment: ImpersonationFactoryAttribute.cs
Description: ImpersonationFactoryAttribute.cs

Attachment: NullImpersonation.cs
Description: NullImpersonation.cs

Attachment: IExternalCredential.cs
Description: IExternalCredential.cs

Attachment: IImpersonationFactory.cs
Description: IImpersonationFactory.cs

Reply via email to