The last few days I had a couple of problems with a Sandbox solution..
I created a trusted proxy to be able to log everything that happened in the sandbox solution to the SharePoint logs. Now it isn’t possible to write directly to the SharePoint logs from within the sandbox solution. Because the SharePoint logging framework relies on APIs that are not available within the sandbox.
This kind of sucks because writing code without any form of logging.. well it’s just not done..
Also, us SharePoint developers had almost all of the time the luxury to write full trusted code… Just put the assembly in the GAC and all is ok… Well with sandbox there is no GAC to speak off and this provides a somewhat different way of coding..
First of all: CAS
Here is a good list of all the execution models. Especially the sentence: “The solution runs using an isolated, low-privilege process” is the most important one.. keyword “low-privilege” ..
Also Tyler holmes blogged about it here with even the mention that we in fact expose our applications to all kinds of unnecessary security risks.
Found a “whitepaper” about Code Access Security in SharePoint 2007 for Administrators and an MSDN link for CAS in WSS 3.0 and MOSS 2007 .
Here is also the msdn link for SecurityAction enumeration .
And last but not least, the start for the entire explanation about Code Access Security .
Alright.. Now that the foundation is there let’s get started…
1. Open Visual studio and select empty SP project (name: TrustedProxyLogger) –> Farm solution
2. Add a code file (.cs) and give it “ProxyLogger” as name
3. next add 3 usings (Microsoft.SharePoint, Microsoft.SharePoint.UserCode and Microsoft.SharePoint.Administration)
4. Now you can add “: SPProxyOperation” behind the class name
5.What you have to do now is to override the execute method and fill in everything needed to be able to log all the information to the SharePoint Logs
6. Explanation of the above code part
a. check if the args are not null (if they are your code may crash and nothing appears in the SP logs
b. depends on the actions that you want to do “RunWithElevatedPrivileges” is needed. But you can leave it out here , just wanted to show that you can do “normal” SharePoint coding here but keep in mind that you are in a full trusted assembly and at FARM level. (more on that later)
c. rest is normal stuff to be able to write trace to the SP logs.
Next up is the ULSProxyArgs class that we have to create (you’ll most likely got the red lines below the ULSProxyArgs ulsargs = args as ULSProxyArgs line..
7. as you can see there are 4 properties (Source, Message, Category Name and LogExpression)
a. as you can see the class must inherit SPProxyOperationArgs
b. there are constructors in place to fill the arguments so in fact you can make the properties private if you want, because they don’t need to be accessible to outside the class
c. the constructor without arguments is private because I don’t want the developer to instantiate an argument class without the basics (Category Name and a source)
8. in the private constructor I do some checks to see if everything is filled in or not null
9. we must also set the proxy args class as serializable and for our first CAS instruction we add the SharePointPermission
a. as we can see in the MSDN explanation of the Security Action enumeration
linkdemand: The immediate caller is required to have been granted the specified permission.
Since the framework of the SharePoint solutions is set to Framework 3.5 there is no need for the second part of the explanation: Do not use in Framework 4.
If SP 15 comes than this will most likely be in Framework 4 and you’ll have to change this.
b. Objectmodel = true : the explanation of MSDN is… Set this property to make a security request or demand for accessing the SP Object model…
Both of the attributes make up for the security call…
Now let’s go back to our ProxyLogger class and apply the CAS that we need..
10. If you set the CAS of the execute method as in the image above.. you compiler will not complain…But your code analysis will say the following:
Warning 1 CA2126 : Microsoft.Security : ‘ProxyLogger’ has one or more overridable methods with link demands that are not matched by an inheritance demand. Apply the following inheritance demands to the type: [SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel = true)]
So if we read this correctly than some CAS is already set? OK, reflector time on the SharePoint assembly (microsoft.SharePoint.dll –> Microsoft.SharePoint.UserCode namespace –> SPOperation class)
As we can see above the class name.. some CAS is already set in the SharePoint assemblies..
Because we’ve only used the linkdemand action the code analysis complains that there is no additional security set. And that extra security is InheritanceDemand
MSDN explanation: Add this security metadata to tell the runtime that a class must have the permission represented by the security metadata attribute to inherit from your class. So in other words.. When I call the class and I have already some security set, it will inherit that security.
So we change our code to this and all is good in code analysis wonderland…
As you can see, I didn’t set any CAS on the execute method.. This is because I’ve set all the security needed at Class level.. all the methods in the class will inherit this CAS setting so no need to add CAS to method level..
11. and last but not least we need to create a feature receiver so that when the feature is activated our trusted proxy will be registered for farm wide use.
12. Add a feature and set the name and description to whatever you want. But the scope must be farm level
13. as you can see in the code above I’m getting the assembly and full name via one of many ways. Once the new SPProxyOperationType is created than I must add it to the collection of operations and update the Usercodeservice.
14. if the feature is being deactivated than the Proxy must be removed from the collection, it’s almost exactly the same code but with a .Remove method instead of an Add method.
15. Also the CAS line must be placed above the class name: “[SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel = true), SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]”
It’s again needed for the Code access security to work correctly.
Because the length of the blog post I’ve decided to split this post in half. With this blog post you can create full trusted proxies with CAS.
In the second part of the blog post I will take the sandbox side under the loop (think it’s written this way ) and how to call the trusted proxy.
On a personal note: Almost nobody uses it, but in the properties of your visual studio solution, select code analysis tab.. Enable it with “Microsoft minimum recommended rules” and build you code again.
Don’t hate it (trust me, you will , especially when you are going to add stylecop as well) but learn from it. As you can see the code analysis advices you to do something but there are more ways to better coding than the advice of code analysis.
Hope it helps someone