©2006 Alexander Homer – alex@stonebroom.com
This series of articles looks at the patterns & practices Enterprise Library tools, and how you can use them in your ASP.NET applications. The five articles are:
· Part 1 - An Introduction to Enterprise Library
· Part 2 - Working with Enterprise Library in ASP.NET
· Part 3 - Using Enterprise Library in ASP.NET Partial Trust Mode
· Part 4 - Extending Enterprise Library with Custom Providers
· Part 5 - Adding Configuration Design Support for Custom Providers
Although originally envisaged as a product for use in Windows Forms (executable) applications, Enterprise Library is proving popular with Web application developers as well. For example, the Data Access Application Block, the Cryptography Application Block, the Exception Handling Application Block, and the Logging Application Block provide useful features that can considerably simplify development of complex applications.
Some blocks, such as the Caching Application Block, contain features that are also supported directly by ASP.NET. However, they can also prove useful in specific scenarios. For example, unlike the ASP.NET Caching mechanism, the Caching Application Block allows the simultaneous use of both a sliding and an absolute expiry time for cached values. The Security Application Block also offers a more flexible approach for features such as authorization and security credential caching than ASP.NET if you need to roll your own mechanisms for this.
The main issue in the past has been the fact that many features of Enterprise Library only work in Full Trust mode, whereas many Web applications must run in lower trust modes. In particular, Medium Trust is a popular choice, as it limits the permissions of many features of ASP.NET and the .NET Framework in general that could compromise operations, while not applying too strict a regime that might limit the functionality of the code.
To resolve this issue, the Microsoft patterns & practices (p&p) group has released a patch for Enterprise Library that allows it to be more easily used in partial trust mode. The patch replaces some of the source code to change the behavior of Enterprise Library. The changes include:
· Removal of most assembly-level permission demands. The default installation of Enterprise Library - January 2006 version - makes demands for all the permissions required for a block at the assembly level, which will cause loading of that assembly to fail in non-Full Trust scenarios. The patched version allows assemblies to load, but you must then write your code so as to fail gracefully when a code access security exception arises. This occurs only in a few isolated places, such as instrumentation calls that write to the Event Log.
· Permission demands defined within the code. Where code within Enterprise Library requires additional permissions, the demands are implemented within the code at that point (either in Enterprise Library code or in the base .NET class libraries), and limited to the features that require the permissions. Therefore, security exceptions will only arise as this particular section of code executes.
· Graceful performance degradation. Where possible, code that demands permissions is written in such a way as to fail gracefully if the requested permissions cannot be granted, instead of generating an outright failure. For example, if the Logging Application Block is unable to call the API that provides information about the current process, this information is simply left out of the message it generates and logs.
To obtain the Partial Trust Patch, you must join the community at the GotDotNet Web site at http://practices.gotdotnet.com/projects/entlib. Follow the Patches link and download the zip file for Partial Trust Patch (2554).
The zip file contains the updated source code files only, and so you must copy them over the existing files in your Enterprise Library source installation and then recompile it. Extract the files from the zip file, maintaining the folder structure within it, and then copy the Src and UnitTests folders over the existing Src and UnitTests folders installed with Enterprise Library. The default installation location for Enterprise Library is %Program Files%\Microsoft Enterprise Library January 2006.
After copying the new files, run the Build Enterprise Library and Copy Assemblies to bin Folder utilities from the Enterprise Library section of your Start menu to recompile all the source code and then copy the updated assemblies into the runtime bin folder. Ensure that the recompilation runs without reporting any errors.
The patch zip file contains an HTML document that describes the patch in detail, and lists the blocks and features that require special permissions when running in any mode other than Full Trust. Selected features of all six of the blocks, plus the configuration system and the instrumentation built into Enterprise Library, are affected. The tables at the end of the HTML document list and describe the affected features, and show the permission you must grant for each one. The document also lists the known issues for the patch.
Having updated Enterprise Library, the next step is to configure your application(s) to run under one of the four partial trust modes - High, Medium, Low, and Minimal. Medium trust is the common choice, and this section describes the process for enabling this mode. The approach is the same for other modes, but using the appropriate trust files instead.
Figure 1 shows the architecture of the trust and configuration files that control the security mode in ASP.NET. The application's Web.config file can contain a <trust> element that defines a partial trust mode (if omitted, ASP.NET assumes Full Trust).

Figure 1 - The architecture of the trust and configuration files for ASP.NET
The <trust> element specifies the location of the policy definitions file using the originUrl attribute. However, in most cases, this is empty, and instead the root Web.config file for the machine (in the folder %WINDIR%\Microsoft.NET\Framework\v2.0.50727\CONFIG) contains a list of the locations of each policy definitions file that corresponds to the four partial trust modes. The following is a section of the standard root Web.config file that defines the security policy file locations. You can see that the file for the High Trust level is named web_hightrust.config, whereas the policy settings for Full Trust are marked as internal - meaning that ASP.NET will use the hard-wired defaults built into the .NET Framework:
<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal" />
<trustLevel name="High" policyFile="web_hightrust.config" />
... Medium, Low, and Minimal definitions here ...
</securityPolicy>
<trust level="Full" originUrl="" />
</system.web>
The root Web.config file also defines the default trust level for all ASP.NET applications running on the machine. You can see in the listing above, immediately after the <SecurityPolicy> section, the <trust> element that specifies the default trust level. Therefore, it is obvious that all you need do to run in a different trust mode is:
· Add the <trust> element to your application's Web.config file and specify the relevant value for the level attribute - as shown in Figure 1 - to set the trust level just for that application
· ... or edit the <trust> element in the root Web.config file to specify the relevant value for the level attribute to set the trust level for all applications on the machine
However, this will not allow all the features of Enterprise Library to execute. The permissions granted in Medium Trust mode are too restrictive for some features of Enterprise Library, including:
· Reading information from configuration files
· Writing to performance counters, the Windows Event Log, and raising WMI events
· Serializing and encrypting data
· Accessing OLE-DB, Oracle, and ODBC databases (though the SqlClient provider for SQL Server will work in Medium Trust mode)
· Obtaining Windows Identity information within the Security Application Block
· Tracing, file listeners, and formatting features of the Logging Application Block
If you want to use any of these features (described in detail in the documentation for the Partial Trust Patch), you must add the grant permissions within the policy definitions file for the trust level you run the application under. However, Microsoft strongly recommends that you do not edit the default policy definitions files provided with the .NET Framework. Instead, you should create a custom trust level policy definition by using a copy of one of the original policy definitions files, and adding the required permission grants to this.
Creating a custom trust level and implementing it within your applications involves five steps:
· Edit the root Web.config file to specify the location and name of your custom policy definitions file.
· Create the custom policy definitions file that grants the required permissions to ASP.NET applications to allow the features you want to use from Enterprise Library to execute.
· Specify the new custom trust level for your application, or for all applications running on the machine.
· Configure your application to use the required features from Enterprise Library
· Edit the application configuration file to prevent Enterprise Library requiring full trust permissions.
The following sections describe these steps in detail.
The first step in creating a custom trust level is to specify the name and location of the policy definitions file. Following the approach taken by the .NET Framework, edit your root Web.config file by adding the new custom <trustLevel> element to the <securityPolicy> section. This element specifies the name of the new custom policy (in this case CustomMedium) and the name and location of the policy definitions file (in this case custom_mediumtrust.config in the same folder as the other policy definitions files):
<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal" />
<trustLevel name="High" policyFile="web_hightrust.config" />
... Medium, Low, and Minimal definitions here ...
<!-- custom trust level policy definitions file -->
<trustLevel name="CustomMedium"
policyFile="custom_mediumtrust.config" />
</securityPolicy>
<trust level="Full" originUrl="" />
</system.web>
The next step is to create the custom policy definitions file. The easiest way to create the new file is to make a copy of one of the original files. In almost all cases, you will want to grant extra permissions to your code, over and above those defined by default for the chosen trust level, and so you will copy the file for your chosen trust level - in this case the file web_mediumtrust.config. Rename the copy to custom_mediumtrust.config, and open it into a text editor or the Visual Studio 2005 XML file editor.
Policy definition files, such as the one you are about to edit, can contain more than one version of the policy level, however those provided with the .NET Framework contain only a single version defined with the <policyLevel version="1"> element. Within the <policyLevel> element are three sections:
· The <SecurityClasses> element contains a list of the permission classes referenced in the <NamedPermissionSets> element, including the name and the .NET Framework class that implements that permission set.
· The <NamedPermissionSets> element contains a list of the permissions for each of the classes listed in the <SecurityClasses> element.
· A series of <CodeGroup> elements contain mappings between the permission classes and the specific permissions required by the .NET Framework.
In general, you will only be concerned with the first two of these sections. In the first, you must add the classes that you want to set permissions for, but which are not already included (such as permission to access an OLE-DB data source, encrypt data, or write to the Windows Event Log). In the second, you add individual permission definitions for these classes and the classes already listed in the first section.
The <SecurityClasses> element in a policy definitions file lists the permission classes, for example:
<SecurityClasses>
<SecurityClass Name="AllMembershipCondition" ... />
<SecurityClass Name="AspNetHostingPermission" ... />
<SecurityClass Name="DnsPermission" ... />
... more security classes here ...
You can add other permission classes for which you want to grant permissions. For example, this listing shows how you can add the OleDbPermission, EventLogPermission, and DataProtectionPermission classes:
<!-- added security permission classes -->
<SecurityClass Name="OleDbPermission"
Description="System.Data.OleDb.OleDbPermission,
System.Data, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="EventLogPermission"
Description="System.Diagnostics.EventLogPermission,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="DataProtectionPermission"
Description="System.Security.Permissions.DataProtectionPermission,
System.Security, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</SecurityClasses>
Having added security classes to the <SecurityClasses> section in the policy definitions file, you can now add or edit the individual permission grants within the <NamedPermissionSets> section. This section contains a series of <PermissionSet> elements, one of which has the Name attribute set to "ASP.Net", and which sets permissions for ASP.NET applications. Inside this element is a series of <IPermission> elements that map to the classes in the<SecurityClasses> section. For example, the default contents of the medium trust policy definitions file contains:
<NamedPermissionSets>
...
<PermissionSet class="NamedPermissionSet" version="1" Name="ASP.Net">
<IPermission class="AspNetHostingPermission" version="1"
Level="Medium" />
<IPermission class="DnsPermission" version="1"
Unrestricted="true" />
<IPermission class="EnvironmentPermission" version="1"
Read="TEMP;TMP;USERNAME;OS;COMPUTERNAME" />
<IPermission class="FileIOPermission" version="1"
Read="$AppDir$"
Write="$AppDir$"
Append="$AppDir$"
PathDiscovery="$AppDir$" />
... more security permissions here ...
</PermissionSet>
... more permission sets here ...
</NamedPermissionSets>
You can see from this how the .NET Framework specifies the settings for ASP.NET under Medium Trust. For example, ASP.NET must be able to read certain environment variables, and access an application's own folders (declared as $AppDir$), in order to execute successfully.
If the policy definition file already contains a definition for the permission you want to grant or change, you simply edit the existing <IPermission> element. For example, the default in Medium Trust mode for the PrintingPermission class is to allow access only to the default printer:
<IPermission class="PrintingPermission" version="1"
Level="DefaultPrinting" />
To permit access to any printer, you just edit the file to change the Level attribute value:
<IPermission class="PrintingPermission" version="1"
Level="AllPrinting" />
In terms of the features of Enterprise Library, one existing <IPermission> element you will usually have to modify is the SecurityPermission class. For example, the web_mediumtrust.config file contains the following <IPermission> element:
<IPermission class="SecurityPermission" version="1"
Flags="Assertion, Execution, ControlThread, ControlPrincipal,
RemotingConfiguration"
To use the serialization features of the .NET Framework, something that occurs in several places within Enterprise Library, you must add permission to use serialization formatters by appending the SerializationFormatter flag:
<IPermission class="SecurityPermission" version="1"
Flags="Assertion, Execution, ControlThread, ControlPrincipal,
RemotingConfiguration, SerializationFormatter"
Other than updating the values of existing <IPermission> elements, you will - in most cases - have to add new <IPermission> elements to the <NamedPermissionSets> section of the file to allow Enterprise Library to execute the features normally prevented in your chosen trust mode. These elements must, of course, match the <SecurityClass> elements you added to the <SecurityClasses> section of the policy definitions file.
For example, earlier you saw the addition of the the OleDbPermission, EventLogPermission, and DataProtectionPermission classes to the <SecurityClasses> section. In the <NamedPermissionSets> section, within the ASP.NET <PermissionSet> element, you can add an <IPermission> element that allows the Enterprise Library Data Access Application Block to use an OLE-DB data provider:
<!-- custom OLEDB permission -->
<IPermission class="OleDbPermission" version="1">
<add ConnectionString="Provider=SQLOLEDB;Database=..."
KeyRestrictions="" KeyRestrictionBehavior="AllowOnly"/>
</IPermission>
Notice how you can use the properties of the OleDbPermission class, through attributes in the <IPermission> element, to specify limitations on the use of this permission. In the listing above, the combination of attributes allows use of an OLE-DB provider, but only with the connection string specified for the ConnectionString attribute. If code attempts to use any other connection string, the code access security system within the .NET Framework will raise a security exception and prevent execution.
The custom policy definitions file can also specify permission grants for the two other classes, EventLogPermission, and DataProtectionPermission, previously shown added to the <SecurityClasses> section. The syntax and the names of the attributes (and, in some cases, child elements) depends on the actual security class. For the EventLogPermission class, you use a child element named <Machine> to specify the name of the machine hosting the Event Log, and the access permission level. This example specifies the local machine Event Log, and allows full access (this is usually the minimum level that will allow writing to the Event Log):
<!-- custom Event Log permission -->
<IPermission class="EventLogPermission" version="1">
<Machine name="." access="Administer"/>
</IPermission>
To allow encryption and decryption of data when using the Cryptography Application Block, you use the DataProtectionPermission class. This <IPermission> element sets the Flags property of the DataProtectionPermission class to allow code to perform both encryption and decryption:
<!-- custom Data Protection permission -->
<IPermission class="DataProtectionPermission" version="1"
Flags="ProtectData, UnprotectData" />
The final step is to specify the new custom trust level you created for the ASP.NET application, or for all ASP.NET applications running on the machine. To specify that an application should run under the new custom trust level, named CustomMedium, you add this attribute to its Web.config file:
<trust level="CustomMedium" originUrl="" />
To specify that all ASP.NET applications on the machine should run under the new CustomMedium trust level, edit the <trust> element immediately after the closing </securityPolicy> element in your root Web.config file (in the %WINDIR%\Microsoft.NET\Framework\v2.0.50727\CONFIG folder) to specify this trust level:
...
</securityPolicy>
<trust level="CustomMedium" originUrl="" />
</system.web>
Once you configure a suitable trust mode, and specify it in your Web.config file, you can add the Enterprise Library blocks you want to use in your application. Run the Enterprise Library Configuration Console from your Start menu and open the Web.config file for your site or application into the console. Use the right-click context menus to add the blocks, and configure them using the properties displayed in the right-hand window of the console. When complete, save the updated Web.config file.
In order to run in any of the partial trust modes, Enterprise Library requires the addition of the attribute requirePermission="false" to the individual <section> elements in the <configSections> of the configuration file. While you only need to add it to the entries for blocks that you use, and which require special permissions in partial trust mode, it is actually easier to add it to all of the <section> elements:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
<!-- must manually add: requirePermission="false" -->
<section name="loggingConfiguration" requirePermission="false"
type="Microsoft.Practices.EnterpriseLibrary.Logging
.Configuration.LoggingSettings,
Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=null" />
<section name="exceptionHandling" requirePermission="false"
type="Microsoft.Practices...ExceptionHandlingSettings, ..." />
<section name="dataConfiguration" requirePermission="false"
type="Microsoft.Practices...DatabaseSettings, ..." />
<section name="instrumentationConfiguration" requirePermission="false"
type="Microsoft.Practices...InstrumentationConfigurationSection, ..." />
<section name="securityCryptographyConfiguration" requirePermission="false"
type="Microsoft.Practices...CryptographySettings, ..." />
<section name="cachingConfiguration" requirePermission="false"
type="Microsoft.Practices...CacheManagerSettings, ..." />
</configSections>
...
Note: some type names and assembly names have been removed or abridged for clarity
However, one issue to be aware of is that you must manually edit the Web.config file after creating it with the Enterprise Library Configuration Console, and every time you update it using the Configuration Console, to add the requirePermission="false" attribute. In the current version of Enterprise Library (the January 2006 release), the Configuration Console removes the requirePermission="false" attribute from each <section> element in the <configSections> section of the Web.config file when it saves the file. You must open the file in a text editor or Visual Studio 2005 and add this attribute to every <section> element after saving your Web.config file:
All applications should guard against the effects of exceptions arising, including security permission exceptions, which may arise for reasons not directly connected with the trust mode. For example, your code may reference a folder that has incorrect file read/write permissions set in the Access Control List (ACL), or attempt to access a network resource for which it does not have permission because the server has been reconfigured.
However, permission exceptions are more likely to occur when you run in a partial trust mode. The major changes you may need to make to your application when using Enterprise Library in less than Full Trust mode are to ensure you handle all possible security (and other) exceptions, and manage them gracefully.
To see the effects of partial trust on the Enterprise Library application block features, and how a custom trust level allows Enterprise Library to run in partial trust modes, the following shows an example application that uses the Caching Application Block, Data Access Application Block, Logging Application Block, and Cryptography Application Block.
The first stage is to add a <trust> element to the application's Web.config file that forces it to run in the standard Medium Trust mode:
<!-- RUN IN MEDUIM TRUST MODE -->
<trust level="Medium" originUrl="" />
Running the application now generates a security exception because the right-hand list box uses the OLE-DB provider to access a database and populate the list. In Medium Trust mode, the OLE-DB provider does not have permission to execute, and raises an OleDbPermission exception (see Figure 2).

Figure 2 - Medium Trust mode causes a security exception for the OLE-DB provider in the Data Access Application Block and for the Logging Application Block.
Notice also that the error message indicates a second exception. The code to populate the right-hand list box contains in the Catch section a call to the methods of the Logging Application Block. This should create an entry in Windows Event Log if an error occurs. However, in Medium Trust mode, Enterprise Library does not have permission to write to the Event Log, and so the .NET code access security mechanism raises an EventLogPermission exception.
The example allows you to create and cache a DataSet generated from a table in the database by the Data Access Application Block. The code to generate the DataSet uses the SqlClient provider, and so will run in Medium Trust mode. However, the Caching Application Block is configured to use the Isolated Storage cache backing store in this example, which uses the .NET serialization features to serialize the data to disk. In Medium Trust mode, attempting to use serialization creates a SecurityPermission exception, as you can see in Figure 3.

Figure 3 - The Caching Application Block cannot serialize data in Medium Trust mode
The example page also demonstrates use of the Cryptography Application Block by allowing you to generate a hash for a string value, and encrypt and decrypt a string value using the Rijndael algorithm. While you can create hash values in Medium Trust mode, you cannot encrypt or decrypt data. Figure 4 shows the result of attempting to encrypt the string in the text box above the Get Hash, Encrypt, and Decrypt buttons. The .NET Framework code access security system raises a DataProtectionPermission exception.

Figure 4 - The Cryptography Application Block cannot encrypt data in Medium Trust mode
To allow the Enterprise Library features to execute in partial trust, as you saw earlier, you must create a custom policy definitions file that contains the required permission grants, and then specify this trust mode for your application. In fact the example application requires only one modification to existing permissions and the three extra permission grants shown earlier in this article. The Caching Application Block requires permission to serialize data:
<IPermission class="SecurityPermission" version="1"
Flags="Assertion, Execution, ControlThread, ControlPrincipal,
RemotingConfiguration, SerializationFormatter"
Meanwhile, the Data Access Application Block, Logging Application Block, and Cryptography Application Block require new permissions added to the custom policy definitions file:
<!-- custom OLEDB permission -->
<IPermission class="OleDbPermission" version="1">
<add ConnectionString="Provider=SQLOLEDB;Database=..."
KeyRestrictions="" KeyRestrictionBehavior="AllowOnly"/>
</IPermission>
<!-- custom Event Log permission -->
<IPermission class="EventLogPermission" version="1">
<Machine name="." access="Administer"/>
</IPermission>
<!-- custom Data Protection permission -->
<IPermission class="DataProtectionPermission" version="1"
Flags="ProtectData, UnprotectData" />
To force the application to run under the new trust mode requires only a change to the <trust> element in the application's Web.config file to specify the CustomMedium policy:
<!-- RUN IN CUSTOM (MEDUIM) TRUST MODE -->
<trust level="CustomMedium" originUrl="" />
Now the application opens without any errors, and the right-hand list box contains the required data. The OLE-DB provider can run using the connection string specified in the policy definitions file (see Figure 5).

Figure 5 - In the custom trust mode, the OLE-DB provider can execute using the specified connection string
Clicking the button to create and cache a DataSet also works fine with the extra permission grant that allows the Caching Application Block to serialize the data before writing it to Isolated Storage. You can see in Figure 5 that the page indicates one item was added to the Caching Application Block cache. Click the button to load the DataSet back from the cache, and you see the data displayed in a GridView control on the page (see figure 6).

Figure 6 - Reading back the DataSet stored in the Caching Application Block cache
The custom trust mode and the corresponding permissions specified by the CustomMedium policy definitions file also allow the Cryptography Application Block to encrypt and decrypt data. Clicking the Encrypt button generates the encrypted version of the text in the text box above the buttons, and displays it in the text box below the buttons (see Figure 7).

Figure 7 - In the custom trust mode, the Cryptography Application Block can encrypt data
The encrypted data is stored in the Isolated Storage cache (using the Caching Application Block), and retrieved and decrypted when you click the Decrypt button. You can see how the Cryptography Application Block returns the original text, and displays in the lower text box (see Figure 8).

Figure 8 - Decrypting data stored in the user's session with the Cryptography Application Block
So far, you have seen how the custom permissions allow the Data Access Application Block, Caching Application Block, and Cryptography Application Block to execute correctly in a custom partial trust mode. This final section shows how the limited OLE-DB permission specified in the policy definitions file, and the permission grant required by the Logging Application Block, work in this custom trust mode.
The <IPermission> element added to the policy definitions file specifies the only permissible connection string:
<!-- custom OLEDB permission -->
<IPermission class="OleDbPermission" version="1">
<add ConnectionString="Provider=Provider=SQLOLEDB; Database=Northwind; Server=.;
Integrated Security=SSPI;
KeyRestrictions="" KeyRestrictionBehavior="AllowOnly"/>
</IPermission>
This is a good way to prevent unauthorized access to databases when using OLE-DB. For example, if you change the connection string that the Data Access Application Block uses for the OLE-DB provider, the code access security mechanism will raise a security exception:
<connectionStrings>
<add name="LocalOleDbConnection"
connectionString="Provider=SQLOLEDB; Database=SecretOne; Server=.;
Integrated Security=SSPI;"
providerName="System.Data.OleDb" />
...
</connectionStrings>
This non-permissible connection string causes the .NET Framework to raise an OleDbPermission exception when the code runs, and before it even attempts to connect to the specified database, as you can see in Figure 9.

Figure 9 - Using a non-permissible connection string raises a security exception
Notice also that the error message indicates that the Logging Application Block successfully added an entry to Windows Event Log this time. The <IPermission> element for the EventLogPermission added to the custom policy definitions file allows the code in the Logging Application Block to write to the Event Log. If you open Event Viewer, you will see the event, as shown in Figure 10.

Figure 10 - The Logging Application Block can access the Event Log in custom trust mode
You should now understand how easy it is to generate custom security policies for your ASP.NET applications, and use them to allow the required features from Enterprise Library to execute on your server.
· Go to Part 4 - Extending Enterprise Library with Custom Providers
©2006 Alexander Homer – alex@stonebroom.com