App Domain Level Impersonation

2019-06-17 08:41发布

I am developing an application that needs to load plug-ins into separate child app domains. Only one plug-in is loaded into one child app domain. Each plug-in requires different Windows identity and those identities are different from the Windows identity used in default (parent) app domain. Each plug-in loads one or more of its child plug-ins.

E.g. Identity of default app domain is Authority\Limited (Authority is either domain name or machine name). Two plug-ins are loaded into two child app domains. The identities of the loaded plug-ins are Authority\Privileged1 and Authority\Privileged2. Authority\Privileged1 and Authority\Privileged2 have all necessary access to databases Database1 and Database2, respectively, whereas the Authority\Limited does not have access to any of aforementioned databases.

When creating child app domain, I call System.AppDomain.SetThreadPrincipal method passing System.Security.Principal.WindowsPrincipal instance. The instance was created from System.Security.Principal.WindowsIdentity instance created from duplicated user token (see http://support.microsoft.com/kb/306158). I have omitted the call to WindowsIdentity.Impersonate method since I am in default app domain while creating the WIndowsPrincipal instance.

I expected that setting the app domains thread principal would be sufficient for the loaded plug-ins to successfully log in to their respective databases and execute some T-SQL statements. To my surprise, the value returned by WindowsIdentity.GetCurrent() method is used when opening a connection to database. The value returned by the method is either process identity or impersonated identity.

Since the process identity does not have permissions necessary to work with the databases, it is not acceptable. Therefore, impersonation must come to play. However, impersonation must take place only in child app domains. Each plug-in exposes methods used to perform loading and unloading of the plug-in. I understand that I have to perform impersonation at the start and undo the impersonation at the end of those methods. However, the impersonation must be done for all threads spawned in the child app domains as well. Since each plug-in loads one or more of its child plug-ins and each plug-in might spawn one or more threads, the impersonation would have to be performed in many places, and that looks very messy.

Is it possible to perform impersonation only once so that affects all threads that are spawned in the child app domains?

1条回答
贼婆χ
2楼-- · 2019-06-17 09:23

No you can't do that - impersonation is per thread and the same thread can have code from several AppDomain on a call stack. This is especially true for plugin systems where main code (from some main AppDomain) calls plugin's logic in separate AppDomain.

Essentially you have to impersonate before calling plugin and revert when you are done. Note that if plugin uses threadpool for its own operations than it will need to impersonate properly.

查看更多
登录 后发表回答