Understanding Plugin sandbox mode

Plugins

Plugins in CRM are great ways to run powerful .NET code and our one of the CRM Developers most powerful tools in his toolbox.

There are lots of steps you need to go through when creating a plugin and there are lots of things which can error.

The knowledge you need is usually built up with a bit of theoretical knowledge and then a lot of practical trying.  The amount of knowledge you need to write a plugin is one of the reasons Why .NET developers struggle with CRM Development

If you are starting out writing plugins, I would recommend my youtube plugin playlist

I would recommend reading my blog post on common plugin errors, which you will certainly experience at some point CRM 2011/2013 – Common Plugin Errors and Isolation Mode

The common errors talks about the  post discusses a deployment common error you might experience, which is you cannot deploy plugins with isolation mode = none if you are not a deployment administrator.

If the isolation mode = “Sandbox” then any CRM Developer who has the security role of Administrator can deploy plugins into a sandboxed environment.

Where can you see the Isolation mode of a plugin

When you create a plugin you can choose two different types of isolation mode

  • Sandbox
  • None

You may have seen these when you are deploying plugins in the CRM Developer toolkit, it’s in the RegisterFile.crmregister file, you can see each assembly has

IsolationMode= “Sandbox”

You can also see what isolation mode of a plugin if you open the Plugin Registration Tool.

  1. open the Plugin Registration tool
  2. connect to CRM instance
  3. Right click on an Assembly and choose update
  4. Now see the Isolation mode

isolation mode

Confusion

When developers talk, naming and terms used can add confusion and slow down people’s understanding.

A plugin assembly has a setting called Isolation mode and this can be set to None or Sandboxed, but you will rarely hear any CRM developers use the term isolation mode.

Instead they will say things like these

  • A plugin is sandboxed
  • CRM online plugins must run in the sandbox
  • it’s a normal plugin

When a CRM Developer mention Sandbox/Sandboxed and plugin they mean the plugin has an isolation mode which equal “Sandbox”

CRM online plugins can only run with an isolation mode = sandboxed

A normal plugin is a plugin which has an isolation mode =  “none”

Often used but not really understood

CRM isolation mode is used all the time by all CRM developers who create plugins but often most CRM developers only have a vague idea of what Isolation mode means.

Most CRM Developers will have heard about Isolation mode with regards to CRM online.  The reason for this is CRM Plugins created for CRM Online organisations must have Isolation mode = “Sandboxed”

What is the Isolation mode?

The first (and best) place to start with understanding Isolation mode and Sandboxed plugins is with this great MSDN article which can be found in the CRM SDK (which should be the first place you look for documentation)

Plug-in isolation, trusts, and statistics

You will notice the isolation mode of a plugin is at the assembly level and not the individual plugin level.

This is why when you create a new plugin there is no setting for isolation mode because it’s at a DLL\project level and you can have many plugins inside one project (or inside one dll).

Isolation Environment

Plugins with an isolation level of “Sandbox” run in an isolated environment and as you can imagine this environment is more secure.  Key point

The sandbox is more secure and some actions are restricted

The restrictions are a bit of mystery, in the sense there is not one all encompassing list of code which will cause an error in a sandboxed plugin.  This can be very frustrating when you deploy a plugin in the sandbox and it throws an error, finding the cause of this can be difficult and frustrating.

The Plug-in isolation, trusts, and statistics article states

isolated environment, also known as a sandbox, a plug-in or custom activity can make use of the full power of the Microsoft Dynamics CRM SDK to access the organization web service. Access to the file system, system event log, certain network protocols, registry, and more is prevented in the sandbox.

The article gives a good description of what this means by saying Plugins deployed in the sandbox are partially trusted (e.g. you only partially trust the plugin and are limiting it’s powers) and plugins which are not in the sandboxed are fully trusted (by you the developer) and you are happy to let them interact with the file system, registry, call other dll’s and web services etc.

Sandboxed and non sandboxed plugins

I recently had some experience with sandboxed plugins because a project I was working on moved all the plugins out of the sandbox.  The first result was I couldn’t not update or publish any plugins because I wasn’t a Deployment admin

The second side effect is I remember the sandbox has its own service.  If you have ever installed CRM you notice there are Sandbox CRM Service and standard CRM Service.  Most CRM Developers know of the services when they do one of the many IISRESETS + Service restart, which usually happens if you have DLL’s in the GAC.  The sandbox service runs all the sandbox plugins.

The sandbox service runs all the sandbox plugins.

I was remote debugging, so instead of attaching the remote debugging to the

  • w3wp.exe – standard plugin
  • CRMASyncService.exe – if the plugin is asynchronous
  • Microsoft.Crm.Sandbox.WorkerProcess.exe – for sandbox plugins

One reason I personally don’t like remote debugging is if someone is debugging a standard plugin, then by debugging the w3wp they stop the whole server whilst and everyone else who is using it.  I have seen some scenarios where other developers and testers have had to stop whilst the one developer debugged his plugin (poor show).

To get around this you can change the plugin to sandboxed and then when you debug you only stop the sandbox service

Sandbox limitations

I have stated previously it’s difficult to know what the limitations are but here some of the limitations taken from the msdn article

  • Access to the file system (C Drive)
  • system event log
  • certain network protocols
  • registry
  • You cannot access any other DLL’s
  • IP addresses cannot be used
  •  Only the HTTP and HTTPS protocols are allowed.
  • In isolated mode you cannot call any external DLL’s\DLL’s in the GAC

This blog had some good restrictions in a bit more detail

  • Attempting to use the AppDomain.CurrentDomain.AssemblyResolve event
  • IO.Path.GetTempPath() [System.Security.Permissions.EnvironmentPermissionException]
  • Any filesystem access code [System.Security.Permissions.FileIOPermissionException]
  • Attempting to use the EventLog [System.Diagnostics.EventLogPermissionException]
  • Attempting to use IsolatedStorage [System.Security.Permissions.IsolatedStoragePermissionException]
  • Any references to Thread.CurrentThread caused a security failure.

Someone tweeted me a great article on security and sandboxed plugins

How to: Run Partially Trusted Code in a Sandbox

The article is fantastic but it does highlight the difficulty developers can experience using the CRM SDK, sometimes the information is there but it’s hard to find.

CRM Online limitations

I believe CRM online sandboxed plugins cannot use LINQ queries, which throws an error due to another transaction being created in the LINQ query.

Custom workflows cannot be used in the CRM online sandbox

Correction – You can call WCF webservices 

I originally put you couldn’t call webservices but I have been corrected thanks to a great comment from Andrii Butenko

To use webservices all you need is to use WebClient if possible like https://msdn.microsoft.com/en-us/library/gg509030.aspx

In case only WCF is available you can call it but you have to manually build binding https://mscrmmindfire.wordpress.com/2013/06/14/calling-external-web-service-from-a-crm-2011-plug-in/

CRM 2015 Online allows custom workflows

Another great comment has caused me to update this post.

Custom workflow activities can now be registered in isolation mode in CRM 2015 online

https://msdn.microsoft.com/en-us/library/gg334752.aspx

Example error

I came across an error which prompted me to write this blog post.  I was trying to serialize some fields and pass them between plugins using shared variables

This forum post below is the same error

https://social.microsoft.com/Forums/en-US/9ce3c4e6-0587-4913-89f8-f3942d7bac93/using-systemwebextensions-in-crm-plugin

Unhandled Exception:

System.MethodAccessException: Attempt by security transparent method ‘TestingSeam.CrmTesting.Execute(System.IServiceProvider)’ to access security critical method ‘System.Web.Script.Serialization.JavaScriptSerializer..ctor(

This error was unusual because it was complaining about access to a critical method.  I wondered why serialization was critical method but thinking about it, serialization must involve writing the data to disk and sandboxed plugins are not allowed to do this.

A Gotcha also occurred when someone changed the plugin to sandbox mode, it stopped the plugin working, so I had to leave a comment in the code to say, this plugin won’t work if the plugin is sandboxed.

Why put plugins in the sandbox

So the question is why would people choose to put plugins in the sandbox.

The most common reason is they are using CRM online and you have no choice because all plugins have to be

Runtime statistics are created  PluginTypeStatistic entity records. These records are populated within 30 minutes to one hour after the sandboxed custom code executes

https://msdn.microsoft.com/en-us/library/gg334752.aspx

This url has an interesting benefit

  1. If the sandbox worker process that hosts this custom code exceeds threshold CPU, memory, or handle limits or is otherwise unresponsive, that process will be killed by the platform. At that point any currently executing plug-in or custom workflow activity in that worker process will fail with exceptions. However, the next time that the plug-in or custom workflow activity is executed it will run normally. There is one worker process per organization so failures in one organization will not affect another organization.

Why haven’t you listed all errors

Some readers maybe dissapointed I haven’t listed all the methods and exact lines of code which will cause sandbox plugins to throw security errors.

Whilst writing this blog post I realised the reason Microsoft have listed all the causes of security errors in sandboxed plugins because there are potentially lots of them and if they tried to list them all, they would miss some. In fact I would say it’s impossible to list them all, so there is no benefit to trying.

The way to think about the sandbox is it’s a bit like a sandpit and the code is a child.  As soon as any code/child tries to get out of the sandpit we throw an error and a parent comes along, tells the child off and throws them back in the sandpit.

This is why sandboxed code is safer because it can’t get onto your server and cause havoc.

Summary

The limitations of sandboxed plugins can be a significant influencing factor for many CRM solutions to be on premise.

The limitation of not being able to call webservices and DLL’s in the GAC can be quite restrictive.

There is a solution using ILMERGE, which is a method of merging a number of different DLL’s into one DLL, which will allow you to use the plugin in a sandboxed environment.  I would be cautious about this approach because if you ask anyone who has done it, they will tell you it wasn’t easy and debugging a merged DLL can be impossible.

Here is a good article on ILMerge issues

Advertisements

Error – the source file is different from when the module was built

This error in the title was very frustrating because it was stopping me test my code.

I had a console app to test the plugin code.  I was building the plugin in a separate project and referencing the dell in my console app.

I would then step through the code but when it got to the point of stepping through the plugin code I was getting the error

the source file is different from when the module was built

 

I understood what is was saying, which is basically the DLL and PDB file were not the same in my console app as the latest file.

This forum has a few answers (they didn’t help)

http://stackoverflow.com/questions/3087390/the-source-file-is-different-from-when-the-module-was-built

 

WHY WHY WHY

So my understanding of the error was my console app wasn’t using the latest dll, pdb file but why.  If you are wondering what the pdb file is, it’s basically the dll file in a code which a debugger can use.

this explanation is a bit better

A pdb file contains information for the debugger to work with. There’s less information in a Release build than in a Debug build anyway, but if you want it to not be generated at all, go to your project’s Build properties, select the Release configuration, click on “Advanced…” and under “Debug Info” pick “None

 

So I looked in the build folder and then I noticed the dll hadn’t been updated since this morning.  I rebuilt the project but it the dll wasn’t updating.

A bit more poking about and I found the DLL was going to a completely different folder.   So I changed the reference in my console app and pow, it worked.

Why was I looking in the wrong folder

When any project but Plugin project gets build you specify a build output path.  You can check this by right clicking on a project and clicking properties

Usually this is

bin\Debug\

output path

but for some reason (I’m pretty sure this was me) the output path had changed to \…\…\…\…\…\BuildDLLs

So the reason why my console app had stopped picking up the correct DLL because the DLL had moved from the directory

bin\Debug\

To

BuildDLLs

 

I changed the output directory to bin\Debug and then it all started to work again.

How this had changed was quite beyond me