In many locked-down environments, administrators do not allow custom code components to have Full trust. Administrators might choose to deploy a solution to the Web application \bin folder, where permissions must be specifically granted. Let’s look at the steps that are involved.
We can show all of this with a small Web Part that connects to a Web service that returns weather information for a specific city. If you build and deploy this Web Part by using Visual Studio 2005 Extensions for Windows SharePoint Services 3.0, the .NET assembly is deployed in the global assembly cache. You cannot intervene in this process on your development computer to configure the solution generation process and deployment differently. Because of the deployment in the global assembly cache, your Web Part gets full trust and does not have any security problems connecting to the Web service.
This scenario works if administrators allow your Web Part assemblies to be deployed in the global assembly cache. However, your Web Part assembly can often end up in the private \bin folder of the IIS Web application. As a Web Part developer, you then depend on the trust level set in the web.config file by administrators. In the end, you can encounter security problems with Web Parts that perform functions similar to our weather Web Part, as described in the following walkthrough.
Let’s assume you have a small Web service that returns the weather for a city, and that there is a Web Part that consumes the information, as shown in Figure 21. (You can work out an example with any type of Web service.)
Figure 21. Web Part consuming a weather Web service
To deploy the Web Part assembly in the private application folder of the IIS Web application instead of the global assembly cache (which is the default when using Visual Studio 2005 Extensions for Windows SharePoint Services 3.0), you can make a change in the manifest file that will enforce this. You can set the DeploymentTarget attribute at the level of the Assembly element to WebApplication instead of GlobalAssemblyCache, as shown in the following example.
<Solution SolutionId="1de3b0fc-78e9-4fe6-ae63-51ea50109982" xmlns="http://schemas.microsoft.com/sharepoint/" >
<FeatureManifests>
<FeatureManifest Location="WeatherWebPart\feature.xml" />
</FeatureManifests>
<Assemblies>
<Assembly Location="WeatherWebPart.dll"
DeploymentTarget="WebApplication" >
<SafeControls>
<SafeControl Assembly="WeatherWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" Namespace="WeatherWebPart" TypeName="WeatherWebPart" Safe="True" />
</SafeControls>
</Assembly>
</Assemblies>
</Solution>
Next, you must create the Windows SharePoint Services solution manually. The following .ddf file shows how to package the different components that make up the Web Part solution.
.OPTION EXPLICIT
.Set CabinetNameTemplate=WeatherWebPart.wsp
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP ;** All files are compressed in cabinet files
.Set UniqueFiles="OFF"
.Set Cabinet=on
.Set DiskDirectory1=Package
manifest.xml manifest.xml
assemblies\WeatherWebPart.dll WeatherWebPart.dll
Features\WeatherWebPart\feature.xml WeatherWebPart\feature.xml
Features\WeatherWebPart\elementManifest.xml WeatherWebPart\elementManifest.xml
Features\WeatherWebPart\WeatherWebPart.webpart WeatherWebPart\WeatherWebPart.webpart
A simple call to Makecab.exe with the .ddf file as input generates the Windows SharePoint Services solution.
makecab.exe /f WeatherWebPart.ddf
You can add the solution to the solution store by executing the following command in a Command Prompt window.
stsadm.exe -o addsolution -filename package\weatherwebpart.wsp
Now, navigate to Central Administration and the Solution Management page. From here you can deploy the solution. Notice that there is no warning because the manifest file does not require the assembly to be deployed in the global assembly cache. Proceed and deploy the solution to one of your IIS Web applications. It’s a good idea to verify in the physical folder that is associated with the IIS Web application (which is located, by default, in Inetpub\wwwroot\wss\VirtualDirectories\IIS Web application name) that the assembly is available in the \bin folder.
Assuming the trust level in the web.config file is not set to Full, you get an exception if you try to run your weather Web Part, as shown in Figure 22.
Figure 22. Weather Web Part deployed in private application folder
The Weather Web Part deployed in the private application folder causes unexpected problems. However, the error is not unexpected. Open the Windows Event Viewer (located in Administration Tools) and you find the full details of the error: "Request for the permission of type 'System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed."
In other words, your Web Part is not granted the permission to communicate with the Web service. How do you solve this? One way is to raise the trust level in the web.config file to Full, but this is risky. From the moment you raise the trust level, all of the privately deployed assemblies get the same basic permissions as the assemblies that are deployed in the global assembly cache. A better solution is to request the permissions that are needed to run the Web Part correctly in SharePoint pages and include that demand inside the manifest file. Administrators who deploy the solution will receive a notification that specific requests for permissions are pending, and they can decide whether to grant these permissions. When proceeding, a copy is made of the policy file that is currently activated, and the requested permissions for the Web Part are added. This new policy file becomes the one activated in the web.config file. Now we can examine all of these steps in more detail.
One piece of information is already available. You have the full details of the required permission (discussed previously). Another piece of information is the full public key blob of the assembly you’re working with. To retrieve this information, open a Command Prompt window, and execute the following command.
Secutil.exe –hex –s WeatherWebPart.dll > keyblob.txt
The result is a text file with the full public key of the assembly in question. The tool used is secutil.exe, which is part of the .NET Framework SDK.
Next, open the manifest file, and add the following CodeAccessSecurity element (a good location is between the FeatureManifests and the Assemblies elements).
<CodeAccessSecurity>
<PolicyItem>
<PermissionSet class="NamedPermissionSet" version="1"
Description="My webpart's permission set">
<IPermission class="AspNetHostingPermission" version="1"
Level="Minimal"/>
<IPermission class="SecurityPermission" version="1"
Flags="Execution" />
<IPermission version="1" Unrestricted="True"
class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<IPermission class="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="True"
version="1">
<ConnectAccess>
<URI uri="$OriginHost$"/>
<URI uri="http://moss:95/webservices/.*"/>
</ConnectAccess>
</IPermission>
</PermissionSet>
<Assemblies>
<Assembly Name="WeatherwebPart" Version="1.0.0.0" PublicKeyBlob="0x00240000048000009400000006020000002400005253413100040000010001000DAF8ED8D945CD2ABB2EE7953A6039B791A725F11B4588AC6D70B3E0648F955E9ED4C3C43CB044B8B0E8A6FF4D4FFBE9E3B9297D45F688A7264534E12414E17539305207EC961DA94DF294E7722CCD9BDBFC95A896E996F57156705D281EC39280BD604E87724556AF5807D146963F19F5B43DB69E1F22695463153A553260D2" />
</Assemblies>
</PolicyItem>
</CodeAccessSecurity>
In the previous code, the IPermission and Assembly element areas are important to review. First, the IPermission element asks for permission to communicate with the Web service (we assume that this Web service is hosted on http://moss:95 IIS Web Application). Next, the Assembly element contains the details of the assembly in question: the name, version, and blob you must retrieve from the keyblob.txt file that is generated via the secutil.exe utility.
When these changes are applied to the manifest file, you must regenerate the Windows SharePoint Services solution and re-add it to the solution store. When you deploy the solution, you will notice a warning at the bottom of the page (see Figure 23) that indicates that the solution contains a code access security policy that will take effect if you continue to deploy the solution. If the administrators do not see a problem with this, they can continue and the Web Part is made available.
Figure 23. Deploying a Web Part solution with a code access security policy
If you followed all of the earlier steps correctly, the weather Web Part works again as before. Behind the scenes, you notice a new entry in the securityPolicy element of the web.config file that looks like the following.
<securityPolicy>
<trustLevel name="WSS_Medium" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_mediumtrust.config" />
<trustLevel name="WSS_Minimal" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_minimaltrust.config" />
<trustLevel name="WSS_Custom" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_custom_wss_minimaltrust.config" />
</securityPolicy>
The new level—WSS_Custom—is now the active trust level in the web.config file.