Logo SharePoint Thoughts   Downloads   About   Up to Bluedog Limited
Code Access Security policies within SharePoint v3
Posted on 8/18/2006 11:29 PM by Maurice Prather

Good news and better news for deploying Code Access Security policies within SharePoint v3... :)

First...

A big thank you ... no, make that a huge thank you ... goes out to everyone that voiced their opinions on this blog, at TechReady, PDC, etc!!  Your comments about the difficulty of deploying code access security policies with your WebPart assemblies helped shape a feature that was long overdue within WSS.

Now for the good news... 

WPPackager is going away.  Bad new... sort of.  However, there is a silver lining. The core functionality of deploying code access security policies has been integrated into v3's Solution deployment engine.

And the even better news...

You will be able to deploy CAS policies starting with Beta 2 TR.

That's right!  The development community will have a way of deploying CAS policies natively within SharePoint.  You will no longer be required to rely on a (buggy) tool.  Oh Yeah!!!

Here's a quick rundown of the CAS deployment capability in v3...

  1. It's very similar to the protocols established by wppackager.  If you haven't read the wppackager documentation in awhile, it might be helpful to briefly review them.
  2. It's just another deployment feature of the Solutions architecture.  If you haven't considered deploying your WebPart assemblies via Solutions, now is the time to reconsider. :)
  3. Unlike wppackager, the new CAS Solutions deployment model will allow you to specify multiple policies within a single Solution package.
  4. You can associate policies to either signed or unsigned assemblies.  Although similar functionality existed with wppackager, it was not widely known.  Depending on how you form your Solution manifest, the resulting CodeGroups within the trust file will utilize either StrongNameMembershipCondition or UrlMembershipCondition classes.

What does the schema look like? 

A quick example is in order ... note the yellow highlighted section ...

<Solution SolutionId="b172f003-d6c7-3e13-f737-a5d84a02e3e5" xmlns="http://schemas.microsoft.com/sharepoint/">
<!--Solution created by InstallAssemblies.exe on 8/15/2006 7:03:53 PM-->
<Assemblies>
<Assembly Location="MyCustomWebParts.dll" DeploymentTarget="WebApplication">
<ClassResources>
<ClassResource Location="MyCustomWebParts.pdb" />
<ClassResource Location="en\two\generic.txt" />
<ClassResource Location="de\two\specific.txt" />
<ClassResource Location="header.html" />
</ClassResources>
<SafeControls>
<SafeControl Assembly="MyCustomWebParts, version=1.0.0.0, Culture=neutral, PublicKeyToken=636addc00401d15b" Namespace="Example.CodeAccessSecurity" TypeName="*" />
</SafeControls>
</Assembly>
</Assemblies>
<DwpFiles>
<DwpFile Location="StandardAspNetWebPart.webpart" />
<DwpFile Location="HybridWSSWebPart.webpart" />
<DwpFile Location="StandardWSSWebPart.dwp" />
</DwpFiles>
<CodeAccessSecurity>
<PolicyItem>
<PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for custom test WebParts">
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" ObjectModel="True" />
<IPermission class="System.Net.WebPermission, System, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1">
<ConnectAccess>
<URI uri="https?://.*" />
</ConnectAccess>
</IPermission>
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlThread, UnmanagedCode" />
<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="UserName" />
</PermissionSet>
<Assemblies>
<Assembly PublicKeyBlob="hexadecimalValueTruncatedForClarity" />
</Assemblies>
</PolicyItem>
</CodeAccessSecurity>
</Solution>

 

Schema rules:

  1. There can only be 1 CodeAccessSecurity node per Solution manifest.
  2. There can be any number of PolicyItem nodes.
  3. Each PolicyItem node can contain only 1 PermissionSer and Assemblies node.
  4. Each PermissionSet node can contain any number of IPermission nodes
  5. Schema of IPermission nodes are defined by the .NET framework
  6. Each Assemblies node can contain any number of Assembly nodes. 
  7. The CodeAccessSecurity/PolicyItem/Assemblies/Assembly node is different than the Solution/Assemblies/Assembly node.
  8. The Assembly node can contain any of the following attributes:
    • Name
    • Version
    • PublicKeyBlob

Commands to add and deploy your Solution which contains a code access security policy...

Add: stsadm.exe -o addSolution -filename "InstallAssemblies_Solution_2052225630.cab"
Deploy: stsadm.exe -o deploySolution -name "InstallAssemblies_Solution_2052225630.cab" -allcontenturls -local -force -allowCasPolicies

Note that stsadm.exe will require the use of the -allowCasPolicies flag for Solution packages that contain CAS policies.

 

What does the trust file look like once the Solution has been deployed?

If you were to use the manifest file from above, the policy file will look like the following file... again note the yellow highlighted sections...

<configuration>
<mscorlib>
<security>
<policy>
<PolicyLevel version="1">
<SecurityClasses>
<SecurityClass Name="AllMembershipCondition" Description="System.Security.Policy.AllMembershipCondition, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="AspNetHostingPermission" Description="System.Web.AspNetHostingPermission, System, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="FirstMatchCodeGroup" Description="System.Security.Policy.FirstMatchCodeGroup, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="NamedPermissionSet" Description="System.Security.NamedPermissionSet" />
<SecurityClass Name="SecurityPermission" Description="System.Security.Permissions.SecurityPermission, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="StrongNameMembershipCondition" Description="System.Security.Policy.StrongNameMembershipCondition, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="UnionCodeGroup" Description="System.Security.Policy.UnionCodeGroup, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="UrlMembershipCondition" Description="System.Security.Policy.UrlMembershipCondition, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="WebPartPermission" Description="Microsoft.SharePoint.Security.WebPartPermission, Microsoft.SharePoint.Security, version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<SecurityClass Name="ZoneMembershipCondition" Description="System.Security.Policy.ZoneMembershipCondition, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</SecurityClasses>
<NamedPermissionSets>
<PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for custom test WebParts" Name="installassemblies_solution_2052225630.cab-b172f003-d6c7-3e13-f737-a5d84a02e3e5-1">
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" ObjectModel="True" />
<IPermission class="System.Net.WebPermission, System, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1">
<ConnectAccess>
<URI uri="https?://.*" />
</ConnectAccess>
</IPermission>
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlThread, UnmanagedCode" />
<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="UserName" />
</PermissionSet>
<PermissionSet class="NamedPermissionSet" version="1" Unrestricted="true" Name="FullTrust" Description="Allows full access to all resources" />
<PermissionSet class="NamedPermissionSet" version="1" Name="Nothing" Description="Denies all resources, including the right to execute" />
<PermissionSet class="NamedPermissionSet" version="1" Name="SPRestricted">
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="WebPartPermission" version="1" Connections="True" />
</PermissionSet>
</NamedPermissionSets>
<CodeGroup class="FirstMatchCodeGroup" version="1" PermissionSetName="Nothing">
<IMembershipCondition class="AllMembershipCondition" version="1" />
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="installassemblies_solution_2052225630.cab-b172f003-d6c7-3e13-f737-a5d84a02e3e5-1">
<IMembershipCondition version="1" class="StrongNameMembershipCondition" PublicKeyBlob="hexadecimalValueTruncatedForClarity" />
</CodeGroup>
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust">
<IMembershipCondition class="UrlMembershipCondition" version="1" Url="$AppDirUrl$/_app_bin/*" />
</CodeGroup>
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="SPRestricted">
<IMembershipCondition class="UrlMembershipCondition" version="1" Url="$AppDirUrl$/*" />
</CodeGroup>
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust">
<IMembershipCondition class="UrlMembershipCondition" version="1" Url="$CodeGen$/*" />
</CodeGroup>
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust">
<IMembershipCondition class="UrlMembershipCondition" Url="$Gac$/*" version="1" />
</CodeGroup>
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="Nothing">
<IMembershipCondition class="ZoneMembershipCondition" version="1" Zone="MyComputer" />
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="Microsoft_Strong_Name" Description="This code group grants code signed with the Microsoft strong name full trust. ">
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="hexadecimalValueTruncatedForClarity" />
</CodeGroup>
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="Ecma_Strong_Name" Description="This code group grants code signed with the ECMA strong name full trust. ">
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="00000000000000000400000000000000" />
</CodeGroup>
</CodeGroup>
</CodeGroup>
</PolicyLevel>
</policy>
</security>
</mscorlib>
</configuration>

From manifest to trust file... what happened?

  1. The PermissionSet from the PolicyItem is directly inserted into the trust file (the first yellow highlighted section).  In this example, the PermissionSet is named "installassemblies_solution_2052225630.cab-b172f003-d6c7-3e13-f737-a5d84a02e3e5-1".  The name is a combination of the installation package ("installassemblies_solution_2052225630.cab") plus the SolutionId ("b172f003-d6c7-3e13-f737-a5d84a02e3e5") plus the PolicyItem index (in this case there is only 1 PolicyItem).
  2. For each Assembly associated with a given PolicyItem in the manifest, one (1) CodeGroup (the second yellow highlighted section) is created. Each CodeGroup will reference the associated PermissionSet within the PolicyItem. Additionally, each CodeGroup is inserted in the first position of the parent CodeGroup container.  This ensure the FirstMatchCodeGroup behavior allows custom policies to be honored before the default WSS permission sets are applied.

Now let's look at how the CodeGroups are created based on the data within the manifest file...

As mentioned in the schema rules section above, the Solution\CodeAccessSecurity\Assemblies\Assembly node can contain three attributes: Name, Version and PublicKeyBlob.  The combination of the three attributes determine which Membership class is used.

Name only --> UrlMembershipCondition
Use this format when assemblies have not been signed and deployment will be isolated to the BIN folder.
Manifest xml
<Assembly Name="MyCustomWebParts" />
Resulting CodeGroup
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="generatedPermissionSetName">
<IMembershipCondition version="1" class="UrlMembershipCondition" Url="$AppDirUrl$/bin/MyCustomWebParts.dll" />
</CodeGroup>
PublicKeyBlob only --> StrongNameMembershipCondition
Use this format when you wish to globally apply a policy to all assemblies with the specified signature.
Manifest xml
<Assembly PublicKeyBlob="hexademical_number" />
Resulting CodeGroup
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="generatedPermissionSetName">
<IMembershipCondition version="1" class="StrongNameMembershipCondition" PublicKeyBlob="hexidecimalValue" />
</CodeGroup>
PublicKeyBlob + Name --> StrongNameMembershipCondition
Use this format when you wish to isolate a policy to a particular signed assembly. The policy will apply to all versions.
Manifest xml
<Assembly PublicKeyBlob="hexademical_number" Name="assemblyName" />
Resulting CodeGroup
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="generatedPermissionSetName">
<IMembershipCondition version="1" class="StrongNameMembershipCondition" PublicKeyBlob="hexidecimalValue" Name="assemblyName" />
</CodeGroup>
PublicKeyBlob + Name + Version --> StrongNameMembershipCondition
Use this format when you wish to isolate a policy to a particular signed assembly and assembly version.
Manifest xml
<Assembly PublicKeyBlob="hexademical_number" Name="assemblyName" Version="0.0.0.0" />
Resulting CodeGroup
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="generatedPermissionSetName">
<IMembershipCondition version="1" class="StrongNameMembershipCondition" PublicKeyBlob="hexidecimalValue" Name="assemblyName" Version="0.0.0.0" />
</CodeGroup>

Finally - reliable, supported deployment of code access security policies is now available in WSS. :)

-Maurice

re: Code Access Security policies within SharePoint v3
Yes, yes, yes!!! I've been very eager to see the syntax for these. Thanks so much for posting this Maurice. This is going to make CAS really usable. No more excuses for setting the trust level ="Full" in the web.config.
 
<Todd />
Todd Bleeker @ 8/20/2006 4:07 PM
re: Code Access Security policies within SharePoint v3
Awesome! Solution packages just go way cooler!
Bil Simser @ 8/24/2006 4:34 AM
re: Code Access Security policies within SharePoint v3
I notice that you used InstallAssemblies to create your Solution file. Is this functionality in the current version or is this under development?
 
John
John Ashman @ 10/23/2006 6:40 AM
re: Code Access Security policies within SharePoint v3
The new version of InstallAssemblies is basically under development.  No eta at this time, though.
Maurice Prather @ 10/24/2006 11:49 PM
re: Code Access Security policies within SharePoint v3
What if you wanted to use an existing permission set that you knew was already defined in the OOTB policies (such as FullTrust)? Or are you always forced to create a new permission set regardless?
Andrew Connell @ 12/11/2006 2:14 PM
re: Code Access Security policies within SharePoint v3
Andrew... 
 
There is no way to leverage existing permission sets; you will need to create a new one.
Maurice Prather @ 1/3/2007 8:48 AM
re: Code Access Security policies within SharePoint v3
I obtain message “Insufficient permissions for setting the configuration section 'defaultProxy'”. What IPermission I must assign?
DkmS @ 2/5/2007 3:27 AM
re: Code Access Security policies within SharePoint v3
Dkms:
 
You should be able to find this information on MSDN.  I believe your starting point will be WebPermission.
Maurice Prather @ 2/8/2007 9:31 AM
re: Code Access Security policies within SharePoint v3
Attribute Unrestricted:
<IPermission class="WebPermission" version="1" Unrestricted="true">
DkmS @ 2/23/2007 4:52 PM
re: Code Access Security policies within SharePoint v3
What should i do to enable my data Viewer web part to display the external RSS feeds properly, if i used an internal RSS feed inside our network, it works properly, but if i used an external one, i get an error in processing the url, we have an automatic proxy, so what should i do to my web.config file, and all the other config files such as the medium and the minimal config files.
 
Any Help
Asem @ 7/22/2007 2:33 AM
re: Code Access Security policies within SharePoint v3
Thanks for the good info. Lots of other places forget about the Unrestricted="true" setting.  Cheers
Shay @ 10/8/2007 1:16 PM
re: Code Access Security policies within SharePoint v3
Thanks for this great insight to including CAS with the solution manifest, Maurice!! it is very helpful.
 
One question - when we retract and subsequently delete the solution from the solution store, the modified custom policy file stays as the "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\wss_custom_wss_minimaltrust.config".
 
Thank you very much for all your help.
buffie @ 10/11/2007 2:09 PM
Developer
Hi What if I want to reference an Ipermission class, that is not part of the securityclasses, can I from the manifest declare a new security class to use in my permissionset? Thanks.
Bo Huge @ 3/11/2010 11:33 PM
re: Code Access Security policies within SharePoint v3
Developer:
You can create your own security permission classes and in turn reference those as needed.  This is exactly what SharePoint's permissions are all about.
 
Maurice Prather @ 3/15/2010 10:48 AM
re: Code Access Security policies within SharePoint v3
i am inserting a list item from a custom webpart using wspbuilder to bin deployment. Workflows are not getting triggered either from automatically when item gets added or through programatically inside runwithelevated privizes from the webpart.
My custom cas policy file
==================
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" Unrestricted="True" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" ObjectModel="True" UnsafeSaveOnGet="True" Unrestricted="True" />
<IPermission class="System.DirectoryServices.DirectoryServicesPermission, System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" version="1" Unrestricted="True" />
================
I am getting the error.. Exception has been thrown by the target of an invocation. allow partial trust assembly.
What permissions I need the permission set which triggers the workflow??
Ghouse @ 8/4/2010 2:29 AM
re: Code Access Security policies within SharePoint v3
Ghouse: Workflow assemblies must be fully trusted.  That's a requirement of the .NET framework.
Maurice Prather @ 8/4/2010 7:30 AM
RSS feed
Microsoft Certified Master
MVP Logo
Follow me on Twitter!
Keyword Search
 
View by category
 

Disclaimer:
The contents of this site represent thoughts and opinions of the authors , not those of anyone else - such as past, present and future employers.  This a forum of the exchange of ideas centered on SharePoint technologies.  It is not a support channel.  :)

Copyright © 2004-2010 Maurice Prather, Inc. All rights reserved.