You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-dev@logging.apache.org by "de la Torre, Douglas" <de...@ugs.com> on 2006/04/06 23:02:04 UTC
RE: Allow log4net to impersonate a user via app-specific mechanism.
Nikko / Team,
Anyone know where this ended up? I'd like to try this out in our
environment, and am curious where to start.
-Doug
-----Original Message-----
From: Nicko Cadell [mailto:nicko@neoworks.com]
Sent: Tuesday, September 28, 2004 3:12 PM
To: Log4NET Dev
Subject: RE: Allow log4net to impersonate a user via app-specific
mechanism.
Doug,
I agree with your points and I see where you are going with the
attribute based configuration.
I will have a think about the best way to add in an Identity factory,
but apart from that I think we know what we are doing. I will have a go
at implementing this and see how I get on.
Cheers,
Nicko
> -----Original Message-----
> From: de la Torre, Douglas [mailto:delatorr@ugs.com]
> Sent: 28 September 2004 02:28
> To: Log4NET Dev
> Subject: RE: Allow log4net to impersonate a user via
> app-specific mechanism.
>
> Hi Nicko,
>
> Thanks for the feedback. Lots of good info, as usual.
>
> > Having a global hook for supplying the credentials may be the way to
> go but I would first like to explore using the config file to
> attach an object to a > property on a specified appender.
>
> I like the clarity of your the approach for specifying config
> file entries.
>
> However, for our application, it would be difficult to support. Why?
> Because it requires updates to the config file. We have lots
> of customers that have deployed our application which uses
> log4net and associated config files. Asking them to edit the
> config file entries is scary - the often muck it up with
> typos, which means all our logging stops. When that happens,
> support becomes very difficult.
>
> We'd like the next version of our application to be able to
> use the impersonation, without requiring them to change their
> config files.
> This would let us simplify the permissions needed to enable
> logging, and not introduce a risk they will break something.
>
> It might be a stretch to impose our deployment needs on the
> broader log4net group, but I'm hoping there is a way to get
> the feature and retain backward compatibility of the config
> files. So far, the only way I can think of for this is via
> the attribute. However, it might make sense to add support
> for both the attribute and the config file entries as you
> outline below. Potentially we could live with just config
> file support, but this would require us to write an upgrade
> utility that could find config files and insert the right
> impersonation statements into the config files (ugh :)
>
> So, these are the options
> 1) Config file support for impersonation
> 2) DLL-attribute support for impersonation
> 3) Both 1 and 2
>
> Seems like it would be easy enough to go with option 3, since
> the underlying impersonation logic works the same, and the
> only difference is how it gets wired into an appender.
>
> Do you see any problem going with option 3?
>
>
>
> > Another question is where in the Appender inheritance
> hierarchy do we
> put the credential?
>
> What would you think of putting a property on Appenders that
> expose credential management? I would probably make an
> interface like:
>
> public interface IImpersonationConsumer
> {
> // See below...IImpersonation replaces
> IExternalCredential
> IImpersonation Impersonation
> {
> get;
> set;
> }
> }
>
> Then, the appenders that support impersonation would
> implement IImpersonationConsumer, exposing the property to
> set the impersonation object to be used. During initial
> configuration, this could be wired up like this:
>
> 1) Check for a <credential> node in the configuration XML
> for the appender.
> - If found,
> - create an instance of the specified appender
> - attach it to the appender (assuming the
> appender implements IImpersonationConsumer)
>
> 2) If credentials not set in 1, then check for the
> ImpersonationFactoryAttribute.
> - If found,
> - instantiate the impersonation factory
> - this factory can create the impersonation object
> - attach it to the appender (assuming the
> appender implements IImpersonationConsumer)
>
>
>
> > I have thought long and hard about the API syntax for the
> IExternalCredential. I think that I prefer the C# using syntax. i.e.
> > where the Impersonate() method returns an IDisposable
> instance. In the
> default or null case this work well because if Impersonate()
> returns null to the
>
> I love it. IDisposable makes sense, and is very clean. Plus
> it is null-friendly. Sounds like a no-brainer
>
>
>
> > I'm not sure that we have got the terminology quite right. While I
> don't necessarily want to just use the MS Windows terminology
> it seems slightly odd to
>
> Perhaps more emphasis on the impersonation and less on the
> 'credential'?
> Instead of IExternalCredential, how about IImpersonation?
>
> public interface IImpersonation : IDisposable
> {
> void Impersonate();
> void Undo();
> }
>
> Note that an Undo should be implicitly called via the
> IDispoable if it hasn't already.
>
> This seems like it would be less tied to what it is in some
> cases (credential), and more tied to what it does
> (impersonation). That way it always works regardless of what
> the underlying code has going on.
>
> For example, this way there is less need to associate it with
> a specific identity, in cases where some external app wants
> to impersonate something other than a single user (maybe from
> a user pool?), or some other scenario where there is not a
> tight association with a specific fixed identity.
>
>
>
> So where are we?
>
> This solution is sounding pretty good. For the most part I
> think we agree on the following
> 1) Impersonation via objects
> - objects are customer-extensible, allowing custom impersonation
>
> 2) Wiring up the impersonation objects at config time via
> config and/or DLL attribute
> 3) Using a property (IImpersonationConsumer) on Appenders
> that support impersonation
> 4) Appenders wrap code that accesses system resources with
> calls to the Impersonation.
>
> The only points still to resolve (or confirm) are the naming
> and maybe the configuration (item 2). Can you think of any others?
>
> -Doug
>
>
> -----Original Message-----
> From: Nicko Cadell [mailto:nicko@neoworks.com]
> Sent: Sunday, September 26, 2004 5:28 PM
> To: Log4NET Dev
> Subject: RE: Allow log4net to impersonate a user via
> app-specific mechanism.
>
> Doug,
>
> Having a global hook for supplying the credentials may be the
> way to go but I would first like to explore using the config
> file to attach an object to a property on a specified appender.
>
> This would allow the credential object to be specified for
> each appender that supported credentials.
> A user could write something like this in the config file:
>
> <appender type="log4net.Appender.FileAppender">
>
> <credential type="log4net.Util.WindowsCredential">
> <username value="DOMAIN\User"/>
> <password value="****"/>
> </credential>
>
> ...
> </appender>
>
> Obviously we would have other implementations of
> IExternalCredential that would not encourage users to embed
> system passwords in plain text files, but you see how it
> could instead specify registry keys to read.
> Alternatively it could be a type specified by the application
> developer which retrieves the credentials from the calling
> application.
>
> <appender type="log4net.Appender.FileAppender">
>
> <credential type="MyApp.MyCredential, MyAssembly" />
>
> ...
> </appender>
>
> What do you think?
>
> Another question is where in the Appender inheritance
> hierarchy do we put the credential? We could put it only onto
> classes that require it or we could put it on to the
> AppenderSkeleton and just let the appenders decide to use it
> or not. Putting it on the actual appenders that use it will
> mean that users won't get confused as to why the property
> exists on the appenders that don't use it.
>
> I have thought long and hard about the API syntax for the
> IExternalCredential. I think that I prefer the C# using syntax. i.e.
> where the Impersonate() method returns an IDisposable
> instance. In the default or null case this work well because
> if Impersonate() returns null to the using block this does
> not cause a problem. I generally like the syntax:
>
> protected void RollFile(string fromFile, string toFile) {
> ...
> using(credential.Impersonate())
> {
> target.Delete();
> }
> }
>
> In the default case this should be fast because Impersonate
> would return null. By default the credential object would be
> a NullCredential singleton instance. This is probably
> slightly slower than checking against null, but you don't
> really know how good a job the JIT will do.
>
> Returning an object to do the revert will be slower than
> calling a Revert method directly, however it should not be
> significant relative to the cost of doing some sort of impersonation.
>
> I'm not sure that we have got the terminology quite right.
> While I don't necessarily want to just use the MS Windows
> terminology it seems slightly odd to impersonate a credential
> as in windows you would impersonate an identity. We either need to use
> ExternalIdentity.Impersonate() or Identity.Impersonate() or
> ExternalCredential.Enable() / Activate() something like that maybe.
>
> What do you think?
>
> Nicko
>
>
> > -----Original Message-----
> > From: de la Torre, Douglas [mailto:delatorr@ugs.com]
> > Sent: 25 September 2004 00:43
> > To: Log4NET Dev
> > Subject: RE: Allow log4net to impersonate a user via app-specific
> > mechanism.
> >
> > 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(I
> > mpersonati
> > 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
> >
>