Wednesday, May 1, 2013

Custom Code Access Security for Web Parts

We've been trying to figure out a way to do some custom searching in MOSS here for a couple weeks.  The first plan of attack was a custom Content Query Web Part using CommonViewFields hooked up to site columns based on a lookup.  Turns out there's a bug doing that which doesn't allow it to work as we wanted (maybe I'll post about that later.)  That bug put a stop to the Content Query solution, so we moved on to another idea.
My friend and co-worker Brad Younge wrote a cool web part that does custom searching.  Two of them, actually.  One for custom queries and another for browsing content.  It's a bit much for what we were trying to do, but once we show it to the customer I think we can modify it to their needs.
Once I got it up and running on my machine, I began getting security errors.  Like:
Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' failed.
Took me a bit of searching to find the culprit.  The trust level on my site is set to WSS_Minimal.  Changing this to WSS_Medium or Full eliminated the errors, but changing the trust level in production wasn't an option so I needed to go down the road of creating some custom code access security settings.  It's not that difficult, but takes some time to track down what entries you need.  I ended up putting the following into my manifest.xml file:
    <CodeAccessSecurity>
        <
PolicyItem>
            <
PermissionSet class="NamedPermissionSet" version="1" Description="Allow access to Statera BrowseForIt">
                <
IPermission class="AspNetHostingPermission" version="1" Level="Minimal"/>
                <
IPermission class="SecurityPermission" version="1" Flags="Execution" />
                <
IPermission class="System.Security.Permissions.RegistryPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"Unrestricted="True" />
                <
IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" Unrestricted="True" />
            </
PermissionSet>
            <
Assemblies>
                    <
Assembly Name="Statera.Moss.Webparts.BrowseForIt" Version="1.0.0.0"PublicKeyBlob="0x002400000480000094000000060200000024000052534131000400000100010031B4F1C0A8692A7AFA369B31D858618DBB26497585F791DD5B8BE9FD2AC7C9554B348BD97E37984CE645AECBE104E14AC99821C94CE0BF726459339D21A4EA9A1220BD7E4E858D9375C4D3B5EE98F3DA5D2D99C9628A03047E81CB409CB04A98633C6E2396E6289FF37A8781E6691697D48528C4B146CE631156F08A87309797"/>
            </
Assemblies>
        </
PolicyItem>
        <
PolicyItem>
            <
PermissionSet class="NamedPermissionSet" version="1" Description="Allow access to Statera Common">
                <
IPermission class="AspNetHostingPermission" version="1" Level="Minimal"/>
                <
IPermission class="SecurityPermission" version="1" Flags="Execution" />
                <
IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"version="1" Read="USERNAME" />
                <
IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" Unrestricted="True" />
            </
PermissionSet>
            <
Assemblies>
                <
Assembly Name="Statera.Moss.Webparts.Common" Version="1.0.0.0"PublicKeyBlob="0x00240000048000009400000006020000002400005253413100040000010001006B801BE53E218D8C0A003278A44D51BB14EDCD573981DD1288A7A492EF389D4BDC4D657F3F3CBF99222C34088AC56CC27FC7CC63821B67F0C70E1D1D7990DD80BCCCA0F455BB97908FFE41A7635172C7B5CAE4E923CE39A65FA5DED4498C750525CF997387F9C89DB3CFB644B97EC7EFACEBD5E081B237511CAADC8104380CDB"/>
            </
Assemblies>
        </
PolicyItem>
    </
CodeAccessSecurity>
When built into the .wsp and deployed with the -allowcaspolicies flag, it does a couple things.  First, it creates a custom trust config file called wss_custom_wss_minimaltrust.config.  That's assuming your site is set to wss_minimal when you deploy.  If it's set at wss_medium, the filename will be wss_custom_wss_mediumtrust.config.  It then sets the trust in web.config to WSS_Custom, changing it from the previous setting. 
When it creates the custom trust file, it takes the wss_minimaltrust.config file and adds content based on what's in the manifest.  For this example, it adds two new PermissionSet entries with the listed IPermission mapping and settings.  
            <PermissionSet class="NamedPermissionSet" version="1" Description="Allow access to Statera Common" Name="Statera.Moss.Webparts.BrowseForIt.wsp-9d32b4ed-ddec-4ba8-804f-d69a3347dfe0-2">
              <
IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
              <
IPermission class="SecurityPermission" version="1" Flags="Execution" />
              <
IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"version="1" Read="USERNAME" />
              <
IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" Unrestricted="True" />
            </
PermissionSet>
            <
PermissionSet class="NamedPermissionSet" version="1" Description="Allow access to Statera BrowseForIt" Name="Statera.Moss.Webparts.BrowseForIt.wsp-9d32b4ed-ddec-4ba8-804f-d69a3347dfe0-1">
              <
IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
              <
IPermission class="SecurityPermission" version="1" Flags="Execution" />
              <
IPermission class="System.Security.Permissions.RegistryPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"Unrestricted="True" />
              <
IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" Unrestricted="True" />
            </
PermissionSet>

The other change to the file takes place down in the CodeGroup section, where it adds one UnionCodeGroup class CodeGroup for each PermissionSet.  These CodeGroups point back to the PermissionSet so WSS knows which policies to apply when code in the listed assembly is run.  
            <CodeGroup class="UnionCodeGroup" version="1"PermissionSetName="Statera.Moss.Webparts.BrowseForIt.wsp-9d32b4ed-ddec-4ba8-804f-d69a3347dfe0-2">
              <
IMembershipCondition version="1" Name="Statera.Moss.Webparts.Common"class="StrongNameMembershipCondition"PublicKeyBlob="0x00240000048000009400000006020000002400005253413100040000010001006B801BE53E218D8C0A003278A44D51BB14EDCD573981DD1288A7A492EF389D4BDC4D657F3F3CBF99222C34088AC56CC27FC7CC63821B67F0C70E1D1D7990DD80BCCCA0F455BB97908FFE41A7635172C7B5CAE4E923CE39A65FA5DED4498C750525CF997387F9C89DB3CFB644B97EC7EFACEBD5E081B237511CAADC8104380CDBAssemblyVersion="1.0.0.0" />
            </
CodeGroup>
            <
CodeGroup class="UnionCodeGroup" version="1"PermissionSetName="Statera.Moss.Webparts.BrowseForIt.wsp-9d32b4ed-ddec-4ba8-804f-d69a3347dfe0-1">
              <
IMembershipCondition version="1Name="Statera.Moss.Webparts.BrowseForIt" class="StrongNameMembershipConditionPublicKeyBlob="0x002400000480000094000000060200000024000052534131000400000100010031B4F1C0A8692A7AFA369B31D858618DBB26497585F791DD5B8BE9FD2AC7C9554B348BD97E37984CE645AECBE104E14AC99821C94CE0BF726459339D21A4EA9A1220BD7E4E858D9375C4D3B5EE98F3DA5D2D99C9628A03047E81CB409CB04A98633C6E2396E6289FF37A8781E6691697D48528C4B146CE631156F08A87309797AssemblyVersion="1.0.0.0" />
            </
CodeGroup>
I think that about covers it.  In one of the articles I read covering code access security the author mentioned every web part developer runs into this at some point, and once you figure it out you don't forget.  I hope he's right!  Oh, and here's a good MSDN articlecovering the topic.

No comments:

Post a Comment