Docstoc

Authorization Manager and .NET Extensibility

Document Sample
Authorization Manager and .NET Extensibility Powered By Docstoc
					Authorization Manager and .NET
Nick Wienholt

Windows Server 2003 has hit the shelves, and contains many new technologies that will interest
.NET developers. One of these technologies is Authorization Manager (AzMan), which provides
a comprehensive framework for allowing the authorization rules of an application to be
managed. AzMan is a COM based technology, but thanks to the wonders of COM Interop,
AzMan can easily be accessed from a .NET application. This article explores the motivation for,
use of, and best practices for leveraging AzMan from the .NET world.

Authorization is one of the most difficult problems that confront software developers. Determining if a
given system activity is permitted for a particular user at a certain time is a deceptively complex
activity. Accurately capturing business rules and translating these rules into the code that performs
authorization checks is a process that the software industry has not perfected, and ongoing development
iterations that are motivated by misinterpreted or missed business rules are the source of many project
failures.
     A number of existing schemes for authorization exist. In Windows, Access Control Lists (ACLs)
are used to describe the permitted operations that a user or group of user are permitted to perform on an
object. It is possible to associate ACLs and ACL-like authorization descriptors with business objects
within an application, but ACLs can be complex to administer, and expressing complex authorization
rules like „a user in role X can perform this operation twice in any 30 day period, but only during
business hours, and the company wide count must not exceed fifty operation executions‟ is not feasible
with a simple structure like an ACL. ASP.NET authorization controls access to pages or files with an
application based on the name or role of a user, but lacks the granularity and flexibility to deal with
complex authorization processes. In the face of complex authorization rules, developers typically resort
to hard coded solutions or at best parameterized solutions where numeric constants are pulled from an
external data store. The code-based approach can be effective, but relies on fixed, know authorization
rules, which is often not the case.

Authentication and Authorization
Authorization and authentication are two topics that are often discussed in the same context, but they
represent two very distinct concepts. A well designed authorization system should not commit the
solution to a particular authentication scheme, and the ideal scenario is to select the best-of-breed
systems for the two tasks. In contrast to authorization, authentication is a problem that is essentially
solved, and most systems have many effective authentication technologies that can effectively be
employed in a solution. In addition to the ubiquitous username / password scheme, applications can use
Windows authentication, ASP.NET Forms authentication (which is typically a special case of
username/ password checked against a database), Passport authentication, client X509 certificates,
smart cards, biometrics, and a range of more obscure authentication technologies. Determining the
correct authentication technology for a system is not usually a difficult task, and the reliable fallback to
username and password combination is usually possible.
     The single greatest problem with authorization is the accurate capture of business rules. The
difficulty in capturing business rules for internal projects that span a number of branches or departments
can be significant. This difficulty is magnified many times over for external consultants who typically
do not have a strong knowledge of the problem domain, and are often the target of obstruction from
internal staff who resent the change that a new system will bring. Entire books, tertiary degrees and
professions exist that are solely dedicated to the activity to business rule capture, and this is eloquent
testimony to the difficulty of the task.
     Even if the current authorization rules of a system can be accurately captured, all businesses
reserve the right to modify their operations in the face of changing business climates, and the
incorporation of customizability and extensibility in the authorization process is a common requirement.
Implementing this customizability and extensibility is a difficult activity – using a parameterized rules
engine can result in some flexibility, but obscure business rules that arrive soon after a new system is
deployed are almost impossible to deal with in a code-based authorization layer. Businesses have a
great ability to conjure up some of the most obscure and seemingly nonsensical authorization rules
imaginable and demand that the new rules can be accommodated at minimal expense, and without the
release of a new version of a system.
Authentication solutions
In the face of these daunting challenges, the developer and architect have previously been forced to
choose between a range of less than adequate solutions. One of the simplest solutions, and one that has
gained wide popularity, is to use Rapid Application Development (RAD) development tools like Visual
Basic, and support frequent releases of an application, typically packages as COM components or .NET
assemblies that are deployed on a middle tier or web server. This option involves giving up on
producing a solution with long-term stability, and simply churn till the budget runs out or the business
tires of supplying new authorization rules. From a development perspective, producing a product this
way is a thoroughly unpleasant and demotivating experience, but the situation is quite common in the
software industry.
     A second solution is to add scripting support to an application, and hand the authorization coding
process over to implementers and business analysts. This solution can be complex to implement, and
requires a certain degree of upfront planning to allow a complete and coherent object hierarchy to be
made accessible to the scripting engine. The scripting solution also carries a higher degree of risk, as
the objects that represent the business entities can be used in ways hard to envision when the object was
developed, and a higher degree of vigilance needs to be maintained in component code to prevent the
system slipping into an invalid state.
     Forcing the client to fully define their current understanding of the business‟ authorization rules,
and producing code that enforces these authorization rules to the letter is also a viable option. It is
reasonable to argue that a company that cannot define its authorization rules has no place to continue in
business, but in many cases, authorization rules are essentially an emergent property of many
individuals going about their daily tasks, and no individual or representative group are capable of
accurately defining the end process. Producing a legal contract that precisely defines all the
authorization rules of an application usually leads to many contract variations as the current rules
change, and new rules are discovered. Clients generally resent variations, regardless of the at-fault
party, and escalating costs on a supposedly fixed price project are a recipe for dispute and aggregation.
     Authorization Manager presents a new solution to the authorization rule problem that provides the
flexibility of the scripting options without many of the risks and expenses.

AzMan
AzMan is based on a simple premise – authorization decisions within many classes of applications are
so fluid and ill-defined that post-deployment modification of the code that implements the decisions is
required. Post-deployment authorization check modifications are accomplished by providing a
framework for handling the parameters needed to make a business rule decisions to script elements,
which allows the complied code that acts on authorization decisions to be totally independent of the
decision making process. In addition to the script support, users can be grouped in application defined
roles, and these roles can be associated with particular application tasks.
     The base element of an AzMan solution is the authorization store, which maintains the various
elements that define an AzMan-implementing application, such as roles, role assignment, business
rules, tasks and operations. There are two storage options available for the authorization store – an
XML file and Active Directory. The XML file option allows simple deployment, and means that
Active Directory does not have to be installed on the host domain. The Active Directory store allows
centralized management and ease of replication across an enterprise, and is ideal for a line-of-business
application that is widely distributed.
     The lowest level item in an authorization store is an Operation. Operations are atomic steps within
an application, such as „Add Item to Cart‟ or „View Report‟. Operations are assigned a constant
numeric value, which is recorded in the authorization store, and the same numeric value is used inside a
.NET code block to conduct an authorization check. The specific method called to perform the
authorization check is AzClientContext.AccessCheck, which takes a parameter that identifies the
operation number, as well as parameters that allow named values to be passed to the AzMan engine.
AzMan uses the role assignments and scripts located in the AzMan store to determine whether an
operation is permitted, and returns this result to .NET code. Operations are the only authorization store
element that .NET code is aware of.
     A complex application will typically define many dozens of operations, and managing each of
these operations individually would present a significant administrative burden. AzMan supports the
concepts of grouping operations into logical groups known as tasks. Tasks are the base unit against
which authorization decisions are assigned in AzMan, and will typically be the unit that experiences the
highest level of administration and modification. In addition to containing operations, tasks can be
made up of other tasks.
     Authorization rules can be expressed in two distinct ways in AzMan. The simplest technique is to
define application roles, and administratively assign these roles to particular tasks. If a user attempts to
perform a particular operation, and their role is not associated with this operation or a task that contains
the operation, the authorization check will fail. This form of authorization check is available in many
technologies, and while it can be effective, the technique lacks the flexibility that is often required. The
second form of authorization check is achieved using authorization scripts, which can be expressed in
either VBScript or JScript. A script-based authorization check is achieved by passing parameters made
available by the code that triggers that check into the script function, which can then use conditional
logic based on parameter values to determine whether the authorization checks is successful.
     Figure 1 illustrates the various AzMan elements, and the relationship between them.




Figure 1. AzMan Elements

     An example of the .NET code that triggers an authorization check is shown in Listing 1. In this
sample, the client context for the user “Admin” is created, and an authorization check on operation 1 is
conducted. Two parameters are passed to the authorization check, and these parameters have a value of
6 and 10. It is apparent from the sample that the code requesting the check has no idea how the check
will be implemented.
Listing 1. Conducting an authorization check from C#

//get client context
IAzClientContext clientContext =
 InitializeClientContextFromName(“Admin”, null, null)

//setup parameters to make check
int operationNo = 1;
object[] paramNames =
 new object[]{"Param1”, “Param2”};
object[] paramValues = new object[]{6, 10};

//call the AzMan engine to make the check
object[] results =(object[])clientContext.AccessCheck(
 "Check1", new object[]{""},
  new object[]{taskNo }, paramNames, paramValues,
   null, null, null);

//deal with the result of the check
if ((int)results[0] == 0){
  //auth. check good
}

The script that determines whether the authorization check succeeds can take any form. The normal
authorization pattern is to use the parameters passed into the script to perform some boolean
expression, as shown in the sample below, but this is not mandatory, and any script function, COM
component, NET component with a COM wrapper or web service can be used to perform the check.
Listing 2 shows an example script that may act on the .NET code in Listing 1

Listing 2. Business rule script example using VBScript

AzBizRuleContext.BusinessRuleResult = False

Dim sum
sum = CInt(AzBizRuleContext.GetParameter("Param1"))+ _
  CInt(AzBizRuleContext.GetParameter("Param2"))

If ( sum < 15 ) Then
 AzBizRuleContext.BusinessRuleResult = True
End If



Authentication Option
Determining the appropriate authentication strategy for an application should not be dependant on the
authorization framework, and vice versa. An AzMan application that does not have backward
compatibility requirements will want to take advantage of the most appropriate authentication strategy,
and not be tied down to a small range of predetermined options. An AzMan application that interacts
with legacy system will usually need to leverage an existing authentication system, and mandating that a
particular authentication is used will not be feasible.
     Thankfully, AzMan does not make any assumptions about the authentication system in use, and it is
possible to use any system that an application requires. The single requirement is that the AzMan client
context will need to map to a particular Windows account. This mapping is performed by application
code through the InitializeClientContextFromName method, which takes the name of a valid Windows
account. Context creation does not require the creation of an impersonation token using low-level
security functions like LogonUser. As the code in Listing 1 illustrates,
InitializeClientContextFromName only requires the account name of the user, which means that an
application never needs to store Windows passwords to create client context.
     The easiest form of authentication to program against is Windows authentication. In this scenario,
Windows is leveraged to perform all authentication functionality, and the code in an AzMan application
simply needs to extract the user name, security identifier (SID) or access token from the current thread,
and call InitializeClientContextFromName, InitializeClientContextFromStringSid or
InitializeClientContextFromToken respectively.
     In some cases, using Windows authentication is not feasible, particularly if the AzMan application
is browser-based. Windows authentication over the Internet is technically possible, but requires the
client to have an Internet Explorer browser and a valid Windows account, and also requires that the
network administrator configure IIS and Windows to allow authentication requests to be properly
handled. If a web application is using client-side certificate-based authentication, IIS can be configured
to map certificate to particular Windows accounts, but client-side certificates can be quite labor
intensive to administer.
     Most web sites prefer simpler authentication technologies like ASP.NET Forms authentication or
HTTP Basic and Digest authentication. Using these authentication techniques, it is possible to set up a
mapping between the authentication credentials and a Windows account name, and use this account
name to call InitializeClientContextFromName. As noted above, AzMan does not require the password
for the mapped Windows account, and as AzMan does not create a security token associated with this
account, there is no possibility of a compromised system using AzMan mappings to gain access to
elevated privileges.
     Mapping roles to users within particular Windows groups will generally make life easier for
AzMan administrators, as many tasks and operations will be statically associated with a particular role,
and an authorization script will not be required. This is not a requirement, and an AzMan application
can choose to authorize users with a custom scheme, and call InitializeClientContextFromName with
the same Windows account for all users. In this case, authorization via role assignments will not be
possible, and all authorization decisions will need to be made via authorization scripts. A user-defined
role and username can be passed to authorization scripts via parameters, and this can be used to
conditionally grant authorization.
     For the extreme case where it is not possible to statically map to a Windows user account, a well
know SID can be created with the Windows API function CreateWellKnownSid, the SID can be
converted to a string with ConvertSidToStringSid, and InitializeClientContextFromStringSid can be
called with the AZ_CLIENT_CONTEXT_SKIP_GROUP flag. This creates an AzMan context that is
not associated with a validated client context, and user information normally accessible through the
client context properties will not be available. Listing 3 shows the creation of an AzMan context with
the WELL_KNOWN_SID_TYPE of WinNullSid.

Listing 3. Creating client context without a know Windows account

using System.Reflection;

[DllImport("Advapi32.DLL")]
public static extern bool CreateWellKnownSid(int
  wellKnowSid, IntPtr pDomainSid, IntPtr pSid,
  ref uint pSize);
[DllImport("Advapi32.DLL")]
public static extern bool
  ConvertSidToStringSid(IntPtr pSid,
 out IntPtr pString);
[DllImport("kernel32.dll")]
static extern IntPtr LocalFree(IntPtr hMem);

public void InitializeContextFromNullSid(){
  //open AzMan app
  string policyFile = "msxml://" + Path.Combine(
    Path.GetDirectoryName(
   Assembly.GetExecutingAssembly().Location),
    "MyAzManFileStore.xml");
  string appName = "MyAzManApp";
  AzAuthorizationStoreClass store =
   new AzAuthorizationStoreClass();
  store.Initialize(0, policyFile, null);
  IAzApplication app =
    store.OpenApplication(appName, null);

  //get null SID
  uint memSize = 256;
  IntPtr pSid = Marshal.AllocHGlobal((int)memSize);
  uint size = memSize;
  const int nullSID = 0;
  bool res = CreateWellKnownSid(nullSID,
   IntPtr.Zero, pSid, ref size);

  //convert to string
  IntPtr pString;
  res = ConvertSidToStringSid(pSid, out pString);
    string stringSid = Marshal.PtrToStringAnsi(pString);
    LocalFree(pString);
    Marshal.FreeHGlobal(pSid);
    pSid = IntPtr.Zero;
    pString = IntPtr.Zero;

    //create AzMan context
    IAzClientContext context =
     app.InitializeClientContextFromStringSid(stringSid,
      (int)
      tagAZ_PROP_CONSTANTS.AZ_CLIENT_CONTEXT_SKIP_GROUP,
      null);
}

Administration and Auditing
Administration of AzMan applications is supported through the Authorization Manager MMC snap-in
that ships with Windows Server 2003. The familiar MMC snap-in interface makes administration
relatively painless, and AzMan elements are grouped in a folder hierarchy that mimics their logical
relations, which makes locating the correct element quite easy. The MMC screen capture in Figure 2
illustrates the similarity between the administrative hierarchy and the logical hierarchy shown in Figure
1. The AzMan application shown is a sample application that is discussed later in the article.




Figure 2. AzMan MMC Administration Console

     Effective auditing of authorization decisions is an important element in secured applications. Long
term storage of the actions performed by particular users is usually the domain of application-defined
database storage, and this is the case for AzMan applications. In addition to the database storage of
successful operations, optional tracking of all attempted operations is an important feature of system
security, and AzMan allow authorization store changes and runtime authorization checks to be recorded
in the to the Security section of the Event Viewer.
     For Active Directory-based AzMan stores, directory service access auditing needs to be enabled at
the domain level, which can be achieved via the use of the Group Policy MMC snap-in.
Auditing of XML-based AzMan stores requires object level auditing enabled at the domain or machine
level, which can be accomplished by the Group Policy or Local Security Policy MMC snap-in. Figure
3 shows the Local Security Policy MMC snap-in with object access auditing enabled.
Figure 3. Enabling Object Level Auditing in Windows Server 2003

     Auditing on authorization store changes and application initialization is controlled at the
authorization store level, and runtime auditing is controlled at the application level. To enable auditing,
right click the MMC node at either the store or application level, select Properties on the context
menu, and select the Auditing tab. Figure 4 shows the auditing options available at the authorization
store level.
                                                                                                   Figure
4. AzMan Authorization Store Auditing Options.

     If the auditing options are correctly configured and auditing is enabled, all attempted authorization
checks for the application will end up in the Security section of the Event Viewer. The logical
authorization parameters passed to the AzClientContext.AccessCheck will not be available as part of
the audit log, but the object name, which is passed as the first physical parameter on the AccessCheck
call, and the AzMan operation will both be recorded. Figure 5 shows the audit details for a successful
authorization check against operation 2 on the sample application.
                                                                                                       Fi
gure 5. Audit Log Details produced by AzMan

Error Reporting
Informing the client why a particular authorization check failed is often an important feature of an
authorization framework. AzMan is a non-visual technology, and has no direct communication with the
end use of the system, which means that informing the user if and when an authorization check has
failed in left entirely to the application developer. The loosely coupled nature of AzMan application
means that access to any operation cannot be assumed at design time, and the application must
gracefully handle the situation where an authorization check fails.
     Script-based authorization checks have the ability to return a string to the application code in the
event of an authorization denial, and this string can be passed through to the end user of the application.
For authorization checks that are determined through role assignments, the AzMan application will only
know whether the check failed or succeeded, and no further error information will be available. To deal
with the variability in error information that can be returned, having a default „you can‟t do this
message‟, and overwriting this if information is returned from the authorization check is generally the
best option. Listing 4 demonstrates this technique.

Listing 4. Authorization failure error reporting

„in BizRules script
AzBizRuleContext.BusinessRuleResult = False
AzBizRuleContext.BusinessRuleString = _
 "Error Message Goes Here"

//in C# code
string errMsg = clientContext.GetBusinessRuleString();
if (errMsg == null || errMsg.Length == 0)
  errMsg = "Business rules prevented this “ +
   ”operation being completed.";

Sample Application
To present a sample application that leverages the AzMan framework, the familiar banking and expense
approval applications will be dispensed with, and an application that has much greater importance for
the average office – the office football tipping competition – will be covered. The application is a
simple ASP.NET application that uses an XML-based draw to populate the interface, and uses the
AzMan framework to determine whether a user is authorized to submit a tip and whether a user is
authorized to access the user administration section of the application.
     The application supports three kinds of authentication, with the mode nominated by pre-processor
directives. The simplest authentication technique is to use Windows authentication, which offloads
responsibility to Internet Explorer and the Windows security system. For application developers who
would prefer to use to use a fixed Windows identity and use AzMan scripts for all authorization
decisions, a preprocessor director allows the AzMan client context to be created using the Windows
Guest account. The final authentication option is the most complex, but is preferable for publicly
accessible AzMan applications. In this option, ASP.NET forms authentication is used, and the
ASP.NET logon is mapped to a particular user account. In the sample, a 1:1 mapping is used, but
introducing a level of indirection through a database lookup is a trivial task.
     User administration in the application is guarded by a role-based authentication check, and only
user contexts that map to the Windows Administrator account can access the page. For tip
authentication, three different business rules ship with the sample. The simplest rule simply cuts off tip
submission after the weekly round of football starts, as shown in Listing 5.

Listing 5. Tip submission cutoff before the week of football starts

AzBizRuleContext.BusinessRuleResult = False

Dim RoundStartTime
RoundStartTime= CDate(AzBizRuleContext.GetParameter( _
 "WeekStart"))

If ( RoundStartTime > (Date + Time) ) Then
 AzBizRuleContext.BusinessRuleResult = True
End If

To demonstrate a more complex rule, the second rule uses the actual start time of a game to determine
when a tip can legally be submitted, which allows tips for Monday Night Football to be made right up
to 8.55 pm Eastern. Finally, to demonstrate a reasonably bizarre business rule that would rarely be able
to be accommodated by a standard authorization framework, a business rule preventing tips for the
Oakland Raiders is demonstrated. A suitable apology is offered to Oakland fans, as shown in Figure 6.
Figure 6. Implementation of strange business rules in AzMan

Conclusion
Authorization Manager allows the business rules of an application to be removed from application
code, and managed via a MMC snap-in. This makes application development easier, as business rules
do not need to be fully nailed down for development to occur, and administrators can implement many
post-deployment application updates without the need to organize a new software release.
     AzMan contexts generally need to map to a Windows user account, and mapping to an account that
is representative of a users roles simplifies administration, but an AzMan application is free to use any
authentication technology it likes.
     AzMan will not be appropriate for all applications, but for corporate applications that tend to have
a rapid rate of business rule change, Authorization Manager may prove to be the technology that
dramatically simplifies application development.

Nick Wienholt is a Windows/ .NET consulting software engineer and architect based in Sydney. Nick has been
involved IT for the last six years, and has work on projects ranging from B2B procurement systems to beach
erosion control system to Digital Rights Management.

In his spare time, he is involved with the running of the Sydney Deep .NET User Group, is writing a book on .NET
Performance for Apress, and is a passionate Cronulla Sharks fan.

Nick can be contact at nick@dotnetperformance.com.

				
DOCUMENT INFO
Shared By:
Categories:
Stats:
views:20
posted:3/31/2011
language:English
pages:11