How to use T4 to generate strongly-typed AzMan wrapper


Update: A new version of the code generator described in this article is available here.

This article provides a brief overview of AzMan and demonstrates how several existing APIs can be used to perform authorization checks in .NET applications. It then discusses shortcomings of the current APIs and  demonstrates how T4 templates can be used to generate a set of C# classes and enumerations that wrap AzMan COM API and allow application developers to write strongly-typed authorization code.

Overview

AzMan (Windows Authorization Manager) is a role-based access control framework. It is included in Windows Server 2008, Windows Vista and Windows Server 2003. It can also be installed on Windows XP as part of Windows Server 2003 Administration Pack. Detailed overview of AzMan is outside of the scope of this article. A good overview of AzMan from application developer standpoint is available in this article written by Keith Brown for MSDN Magazine back in November of 2003.

Perhaps the most powerful aspect of AzMan is the separation of concepts of roles and operations. At the lowest level of AzMan security policy, developers define the set of operations performed by the application and work with business analysts to group operations into high-level tasks. Unlike operations, tasks are named using business terms and can be understood by users and managed by administrators. Once operations are defined, developers are free to implement authorization checks in the application code, while business analysts work with users to define business roles that require performing specific tasks and determine role assignments (which users or user groups are authorized to perform which roles). Because application code is aware of only operations, business is free to change the security policy without breaking the application.

Unfortunately, it is difficult to take full advantage of AzMan in .NET applications. Although several APIs are available, none of them do it justice. Examples below demonstrate how you can perform authorization checks using different APIs. They will be using the following AzMan security policy stored in XML file called MyAzManStore.xml.

  • My Application
    • Operations
      • My Operation 1
      • My Operation 2
    • Tasks
      • My Task 1 (My Operation 1)
      • My Task 2 (My Operation 2)
    • Roles
      • My Role 1 (My Task 1)
      • My Role 2 (My Task 2)
    • Role Assignments
      • BUILTIN\Users (My Role 1)

This policy defines two operations in application called “My Application”. There are two tasks containing one operation each and two roles each authorized to perform a single task. BUILTIN\Users group is assigned to only one application role, effectively authorizing it to perform “My Operation 1″ but not “My Operation 2″.

ASP.NET Role Manager

ASP.NET role manager provides an API for managing application roles and users’ membership of roles. ASP.NET role manager can be configured to use the AuthorizationStoreRolePrivider to work with an AzMan policy. Here is an extract from application configuration file that does that.

<connectionStrings>
  <add name=LocalPolicyStoreconnectionString=msxml://C:/Test/AzManPot/MyAzManStore.xml/>
</connectionStrings>
<system.web>
  <roleManager defaultProvider=RoleManagerAzManProviderenabled=true>
    <providers>
      <add name=RoleManagerAzManProviderapplicationName=My ApplicationconnectionStringName=LocalPolicyStoretype=System.Web.Security.AuthorizationStoreRoleProvider, System.Web,
        Version=2.0.0.0, Culture=neutral, publicKeyToken=b03f5f7f11d50a3a/>
    </providers>
  </roleManager>
</system.web>

This configuration file defines a connection string called LocalPolicyStore that points to AzMan XML policy store. It also defines a default role manager provider called RoleManagerAzManProvider which uses the connection string to connect to the AzMan store and access application called My Application in it.

Here is an example of authorization check that determines if the current windows user can perform a given role.

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
// …
bool authorized = Roles.IsUserInRole(“My Role 1″);
// …

Because ASP.NET role manager uses Thread.CurrentPrincipal, this code changes AppDomain principal policy to WindowsPrincipal. This makes windows identity of the current user available to the AuthorizationStoreRoleProvider. The actual authorization check is performed using Roles.IsUserInRole method, which takes name of AzMan role as a parameter.

As you can see, using ASP.NET role manager is easy. Despite of what it’s name suggests, nothing prevents you from using ASP.NET role manager in windows applications. However, ASP.NET role manager forces you to use application roles instead of operations, which defeats the purpose of using AzMan to separate application code from security policy.

More information about using AzMan with ASP.NET role provider can be found in this article on MSDN.

Enterprise Library Security Application Block

Security Application Block of Enterprise Library provides an API for implementing common authorization-related functionality in .NET applications. It can also be configured to use AzMan policy store. Here is an extract from configuration file that does that.

<configSections>
  <section name=securityConfigurationtype=Microsoft.Practices.EnterpriseLibrary.Security.Configuration.SecuritySettings,
    Microsoft.Practices.EnterpriseLibrary.Security, Version=3.1.0.0, Culture=neutral,
    PublicKeyToken=b03f5f7f11d50a3a/>
</configSections> 

<securityConfiguration defaultAuthorizationInstance=“” defaultSecurityCacheInstance=“”>
  <authorizationProviders>
    <add name=AzMan ProviderstoreLocation=msxml://C:/Test/AzManPot/MyAzManStore.xmlapplication=My Applicationscope=“” auditIdentifierPrefix=AzMan Authorization Providertype=Microsoft.Practices.EnterpriseLibrary.Security.AzMan.AzManAuthorizationProvider,
      Microsoft.Practices.EnterpriseLibrary.Security.AzMan, Version=3.1.0.0, Culture=neutral,
      PublicKeyToken=b03f5f7f11d50a3a/>
  </authorizationProviders>
</securityConfiguration>

This configuration defines an authorization provider named AzMan Provider, configured with storeLocation attribute to point to an AzMan security policy store and and application attribute to refer to a specific application in it.

Here is an example of authorization check that determines if current windows user is authorized to perform a given operation.

IAuthorizationProvider authorizer =
    AuthorizationFactory.GetAuthorizationProvider(“AzMan Provider”); 

WindowsPrincipal currentPrincipal = new WindowsPrincipal(
    WindowsIdentity.GetCurrent()); 

Console.Write(“Can current user perform My Operation 1?…”);
bool authorized = authorizer.Authorize(currentPrincipal, “O:My Operation 1″);

This code uses AuthorizationFactory to create an AzManAuthorizationProvider based on its name (as defined in application configuration file). It then creates a WindowsPrincipal object for the identity of the current user. The actual authorization check is performed using Authorize method, which takes a principal object and a name of AzMan operation prefixed with “O:” as parameters.

As you can see, Security Application Block is more complex to configure and use than ASP.NET role provider. However, it does allow you to perform authorization checks using operations instead of roles and take advantage of AzMan’s decoupling of application code and security policy.

More information about using AzMan with Security Application Block can be found in this article on MSDN.

Primary Interop Assembly

AzMan’s native API is COM-based and comes with a primary interop assembly for .NET applications (Microsoft.Interop.Security.AzRoles). Although this API provides full access to AzMan functionality, it was designed for consumption in scripting languages, like JavaScript. This makes using it in C# rather cumbersome. Here is a code example that determines if the current user is authorized to perform a given operation:


AzAuthorizationStore store = new AzAuthorizationStoreClass();
store.Initialize(0, “msxml://C:/Test/AzManPot/MyAzManStore.xml”), null);
IAzApplication application = store.OpenApplication(“My Application”, null);
 

IAzClientContext context = application.InitializeClientContextFromToken(
    (ulong)WindowsIdentity.GetCurrent().Token.ToInt64(), null); 

object[] results = (object[])context.AccessCheck(“My Object”,
    new object[] { string.Empty },
    new object[] { 1 }, // My Operation 1
    null, null, null, null, null);
bool authorized = ((int)results[0] == 0);

This code creates opens a XML security policy store and opens an application called “My Application” in it. It then creates a context object for the current WindowsIdentity. The actual authorization check is done using AccessCheck method of the context object. This method takes an array of operation IDs as the third parameter and returns an array of integer values, one for each operation, where 0 indicates that current user is authorized to perform the corresponding operation.

There are multiple problems with this code - we have to use a lot of type casting, pass null values to unused parameters. We didn’t even see the COM cleanup and error handling, which was removed from this example for readability.

More information about using AzMan API can be found in this MSDN Magazine article.

Analysis

Although ASP.NET role manager is the easiest option, only Security Application Block of Enterprise Library and AzMan’s COM API allow you to perform authorization checks using operations and separate application source code from security policy. Therefore we will not be considering ASP.NET application role manager as a viable option for working with AzMan.

Duplication of Operation Definitions

Both of the remaining two options require you to maintain a set of operation definitions in application source code, such as operation names (for Security Application Block)

public const string MyOperation1 = “O:My Operation 1″;
public const string MyOperation2 = “O:My Operation 2″;

or operation IDs (for AzMan native API).

public const int MyOperation1 = 1;
public const int MyOperation2 = 2;

This is pure duplication because the actual operations are defined in the AzMan security policy. Maintaining two sets of definitions will become more and more difficult as the size of the application and the number of its operations increases. Ideally, we would want to synchronize operation definitions in application source code with the AzMan security policy automatically.

Usability

From usability standpoint, using AzMan’s COM API directly in the application code is not acceptable. It is simply too complex and error-prone.

While usability of Security Application Block is acceptable, it is certainly not ideal. It requires using special prefixes in operation names, which is counterintuitive. Being abstract, it also doesn’t help you to understand which operations are available for authorization checks or where the constants for operation names are defined.

Ideally, we want authorization checks to use enums to define operations instead of string or integer constants. Enums provide better IntelliSense experience for developers and allow us to restrict the set of possible operations from open-ended int or string values to an explicitly defined list.

Ideal Solution

Here is a usage scenario for my ideal AzMan authorization API.

public enum MyApplicationOperation
{
    MyOperation1 = 1,
    MyOperation2 = 2
} 

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
// … 

AuthorizationManager azMan = new AuthorizationManager(
  “msxml://C:/Test/MyAzManPot/MyAzManStore.xml”));  

bool authorized = azMan.CanPerform(MyApplicationOperation.MyOperation1);
// or
azMan.Authorize(MyApplicationOperation.MyOperation1)
  • It uses an enumerated type to define operation IDs
  • It allows using Thread.CurrentPrincipal to determine windows identity of the current user. This allows developer to avoid passing an extra parameter for each authorization check, making the code more compact.
  • It defines strongly-typed authorization methods using enumerated type for operation IDs.
  • It provides a method (CanPerform) that returns a boolean value indicating whether current user is authorized to perform a given operation
  • It also provides a method (Authorize) that throws SecurityException if user is not authorized to perform a given operation
  • It doesn’t force developer to use application configuration to specify security policy store location

Admittedly, this is a lot to ask for. In particular, the wish to have strongly-typed interface based on enums cannot be implemented using generics and has to be code generated. It also shows some of my pet peeves by taking a stab at over-reliance of some .NET APIs on configuration files. However, generating this API using T4 is very straightforward (and quick if you download the ready-to-use templates attached to this article).

Implementation

Attached source code contains several T4 templates described below. These templates use AzMan’s COM API to access security policy specified using XML file name. Using an XML file to store AzMan security policy during development allows you to store it along with the source code of your application under version control. You can also conveniently edit it using Authorization Manager MMC console.

AzManOperation.tt

This is a T4 template that generates a single enumerated type that represents operations in a given AzMan application. It is located in the Templates folder of AzManPot project available for download at the end of this article. This template takes namespace name, AzMan XML policy file name and AzMan application name as parameters. It is intended to be included one or more times in your project, once for each application your AzMan security defines.

This templates generates name of the enumerated type by taking the given application name, stripping all white space and special characters from it and appending Operation to it. For example, for application “My Application” enumerated type will be called MyApplicationOperation. Declaration of the enumerated type is placed in the namespace whose name is generated based on the Namespace template parameter.

Each enumerated value represents a single AzMan operation. Name of the enumerated value is generated by stripping all white space and special character from the actual operation name. Enumerated values are explicitly specified based on AzMan operation IDs.

AzManWrapper.tt

This is a T4 template that generates AuthorizationManager class, that wraps AzMan’s COM API and provides a set of four strongly-typed methods for each application in a given security policy. It is located in the Templates folder of the AzManPot project available for download at the end of this article. The template takes namespace name and AzMan XML policy file name as parameters. It is intended to be included once in your project (unless you have to use multiple AzMan security policies in your application).

For each application in the given XML security policy, this template generates the following methods. It generates enumerated type name (i.e. MyApplicationOperation) using the same rules as AzManOperation.tt described above.

public void Authorize(MyApplicationOperation operation);
public void Authorize(WindowsIdentity identity,
  MyApplicationOperation operation);
public bool CanPerform(MyApplicationOperation operation);
public bool CanPerform(WindowsIdentity identity,
  MyApplicationOperation operation);

Generated AuthorizatoinManager class also implements IDisposable pattern to allow you control releasing of COM resources explicitly.

Usage

In order to use the attached templates, you will need Visual Studio 2005 Standard (or higher) Edition and DSL Tools installed on your computer. If you are running Windows XP, you will need to install AzMan as part of the Windows Server 2003 Administration Pack; copy AzMan primary interop assembly (Microsoft.Interop.Security.AzRoles) from a computer running Windows Server 2003 (typically located in C:\Windows\Microsoft.NET\AuthMan folder) and install it in GAC. To run demos, you will also need Enterprise Library 3.1 installed on your computer. To run unit tests, you will need Visual Studio 2005 Test Edition. You may also want to install T4 Editor by Tangible Engineering, which adds IntelliSense and syntax highlighting to Visual Studio text editor for T4 templates.

Here are typical steps for working with AzMan security policy and generating a strongly-typed authorization API.

  • Add your existing AzMan XML policy file to your project. Right-click the policy file in Solution Explorer, click “Open With…” and use AzMan.cmd (included in AzManPot project of the attached source code) to open the file in Authorization Manager MMC console. In MMC console, right-click Authorization Manager node, select “Options” and make sure that Authorization Manager is in Developer Mode. Otherwise, you will not be able to edit operations. Add new or modify existing operations as necessary.
  • Add a reference to Microsoft.Interop.Security.AzRoles assembly, which should be available in the global assembly cache. (See notes above about using AzMan on Windows XP).
  • Copy AzManOperation.tt and AzManWrapper.tt from the attached source code to the location where they will be available to your C# project. Steps below will assume that templates are stored in Templates directory in your project. You will want to store these files in your source control system along with the rest of your application source code. If you want to add them to your C# project, make sure to remove TextTemplatingFileGenerator from Custom Tool property of the files.
  • For each application in your security policy, add a new text file called MyApplicationOperation.tt to your project, where MyApplication is the name of the application in security policy with white space and special characters removed. Enter the following template code, which includes AzManOperation.tt using relative file path and assigns its parameters.
    <#
        NamespaceName = “MyCompany.MyApplication.Security”;
        AzManXmlFileName = “MyAzManStore.xml”;
        ApplicationName = “My Application”;
    #>
    <#@ include file=Templates\AzManOperation.tt#>
  • Saving MyApplicationOperation.tt will make T4 generate an enumerated type in MyApplicationOperation.cs. Any code generation errors will be reported in the Visual Studio Error List window. Resolve errors (if any) and eyeball the generated code to make sure it looks OK. You should see something like this.
    // <autogenerated>
    //   This file was generated from T4 template MyApplicationOperation.tt.
    // </autogenerated>
    using System; 
    
    namespace MyCompany.MyApplication.Security
    {
        /// <summary>
        /// This is my application
        /// </summary>
        public enum MyApplicationOperation
        {
            /// <summary>
            /// This is operation 1 in my application
            /// </summary>
            MyOperation1 = 1, 
    
            /// <summary>
            /// This is operation 2 in my application
            /// </summary>
            MyOperation2 = 2
        }
    }
  • Add a new text file called AuthorizationManager.tt to your project with the following template code, which includes AzManWrapper.tt using relative file path and assigns its parameters.
    <#
        NamespaceName = “MyCompany.MyApplication.Security”;
        AzManXmlFileName = “MyAzManStore.xml”;
    #>
    <#@ include file=Templates\AzManWrapper.tt#>
  • Saving AuthorizationManager.tt will make T4 generate AuthorizationManager.cs. Any code generation errors will be reported in the Visual Studio Error List window. Resolve errors (if any) and eyeball the generated code to make sure it looks OK. You should see something like this.

Now you  should have your strongly-typed AzMan API completely generated and ready to use in your application code. Check out Demos\AzManStronglyTypedDemo.cs and AuthorizationManagerTest.cs for code examples.

Wish List

Here are some ideas I considered while working on this article. I may revisit them in the future, but for now, I simply ran out of time. I would love to hear from you If you implement any of them in your project or if you would be interesting on working on them together.

Integration with .NET Security Framework

AuthorizationManager class generated by T4 template in this article is a custom class. Instead, it would be nice to extend the .NET security framework and generate OperationPermission and OperationPermissionAttribute classes for imperative and declarative authorization checks, similar to the built-in PrincipalPermission and PrincipalPermissionAttribute classes.

Integration with Visual Studio

T4 templates used in this article follow the one type per source file best practice and require you to add multiple template files to your Visual Studio project manually. It would be nice to use Visual Studio extensibility to add all required template files to the project automatically, based on all applications in a given AzMan security policy.

Instead of requiring you to specify NamespaceName for each template, it would also be nice to use Visual Studio extensibility interfaces to automatically determine namespace for the generated types based on location of the templates in a project and project’s default namespace.

Enterprise Library Support

I know that many people like Enterprise Library and will prefer to use Security Authorization Block instead of rolling out their own AzMan wrapper, no matter how strongly-typed, light-weight and easy to use it is. It would be nice to have a template that generates a static class with string constants for operation names instead of an enumerated type.

Security Policy Deployment Support

While using XML security policy files during development is a great option, you don’t want to deploy them to your production environment. For performance reasons, it is best to use Active Directory or Microsoft SQL Server to store AzMan security policy in production. It would be nice to automatically generate a script or .NET Installer class for deploying applications and operations defined in developer’s XML policy file to the production Active Directory or SQL Server policy store.

About T4

T4 (Text Template Transformation Toolkit) is a template-based code generation engine. It is available in Visual Studio 2008 and as a download in DSL and GAT toolkits for Visual Studio 2005. T4 engine allows you to use ASP.NET-like template syntax to generate C#, T-SQL, XML or any other text files.

For more information about T4, check out my previous article.

Download

Source code of the T4 templates and examples used in this article can be downloaded here.
New version of the code generator described in this article is included in T4 Toolbox and described here.


Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Great post. Just the way I want to work with the AzMan authorization API. Got it working with with my Active Directory.

Cool,
leaning about APIs that can be used to perform authorization checks in .NET application made my life more easier

thanks for bothering to post it