I am looking for a simple and secure way to access plugins from a .NET application. Although I imagine that this is a very common requirement, I am struggling to find anything that meets all my needs:
I have investigated both MEF and MAF, but I am struggling to see how either of them can be made to fit the bill.
Assuming my understanding is correct, MAF is unable to support the passing of generic types across its isolation boundary, which is essential to my application. (MAF is also very complex to implement, but I would be prepared to work with this if I could solve the generic type problem).
MEF is almost a perfect solution, but appears to fall short on the security requirement, as it loads its extension assemblies in the same AppDomain as the host, and thus apparently prevents sandboxing.
I have seen this question, which talks of running MEF in a sandboxed mode, but doesn't describe how. This post states that "when using MEF you must trust extensions not to run malicious code, or offer protection via Code Access Security" but, again, it doesn't describe how. Finally, there is this post, which describes how to prevent unknown plugins from being loaded, but this is not appropriate to my situation, as even legitimate plugins will be unknown.
I have succeeded in applying .NET 4.0 security attributes to my assemblies and they are correctly respected by MEF, but I don't see how this helps me to lock out malicous code, as many of the framework methods that might be a security threat (such as methods of System.IO.File
) are marked as SecuritySafeCritical
, which means that they are accessible from SecurityTransparent
assemblies. Am I missing something here? Is there some additonal step I can take to to tell MEF that it should provide internet privileges to plugin assemblies?
Finally, I have also looked at creating my own simple sandboxed plugin architecture, using a separate AppDomain, as described here. However, as far as I can see, this technique only allows me to use late binding to invoke static methods on classes in an untrusted assembly. When I try to extend this approach to create an instance of one of my plugin classes, the returned instance cannot be cast to the common plugin interface, which means that it is impossible for the host application to call into it. Is there some technique I can use to get strongly-typed proxy access across the AppDomain boundary?
I apologize for the length of this question; the reason was to show all the avenues that I have already investigated, in the hope that somebody can suggest something new to try.
Many thanks for your ideas, Tim
Because you're in different AppDomains, you can't just pass the instance across.
You'll need to make your plug-ins Remotable, and create a proxy in your main app. Have a look at the docs for CreateInstanceAndUnWrap, which has an example of how all this could work towards the bottom.
This is also another much broader overview by Jon Shemitz which I think is a good read. Good luck.