Software Development
Blogs and Discussion
developer.*
Books Articles Blogs Subscribe d.* Gear About Home

Implementing RBAC on .Net

Recently I worked on RBAC (Role based access control) implementation within .Net. A comprehensive work on this topic is done by Mark Strembeck XoRBAC Home Details on RBAC concept can be found at NIST RBAC

While the design approach given in Strembeck's work was comprehensive enough to be realized on .Net, the default implementation (done on XoTcl) used extensive patterns from the language (e.g. ability to use an object as a class!), so a quick port of that to a complete .Net implementation of the design would have taken a bit of an effort in my current project.
Well, instead of then implementing the solution, I selected MS Authorization Manager (I know folks will say, Dah... that would have been a no brainer). This is a small library and a management console prrovided on Windows 2003 and 2000 that implements most of the RBAC requirements.

Drawbacks in AzMan implementation

1. One drawback of AzMan (A zee man not Ass man, short for Authorization manager) is its MMC based model that is very administrators centric, while
RBAC being a business model driven artifact rather requires a more user centric admin functions ( e.g. a website driven system would require a web interface mangement of RBAC model).

2. The AzMan implementation is integrated seamlessly with the Windows integrated Authentication model, which in my own opinion is a best way to support Single-Sign On model on enterprise solutions utilizing distributed web services, also the fact that it can be configured with only using Kerberos behind the scene). In many solution using windows integrated authentication may not be an option, and that was the case in our solution as well (this is also true when you can't use windows PDC which is mandatory for Kerberos based authentication).

Overcoming the above two drawbacks
------------
1. To overcome the first drawback, the API driven model of AzMan library can easily be used via a custom admin interface.

As a matter of fact the built-in web configuration management tool in ASP.Net 2.0 utilizing the Role Provider model relies on such approach.

2. The second drawback is somewhat solved by AzMan through using a custom SID encoding mechanism where you can create custom SID for your database driven users and register that in AzMan store. The problem with that is that you will then definitely need a custom Admin interface because AzMan default MMC do not support custom SID.

Solution
--------
So, one solution then is to build a custom Admin interface which plugs in with the custom user membership database and use AzMan APIs to manage roles and memberships.

One can argue why not use the default Asp.Net 2.0 role management provider could have worked, but that abstraction lacks the primary reason of using AzMan, the Permissions (which is a core concept in XoRBAC and RBAC), also it can't authorize against custom user databases, i.e. it can only work with windows integrated authentication.

Also, due to the use of technologies that are potentially at the early stages of their evoluttion, we wanted a more intent/attribute based access to RBAC, so that in future we can swap the backend of RBAC with any other solution.

To some extant the PrincipalPermission attribute in .Net will help, but again it is only role centric not permission centric. For this we developed custom attributes for representing RBACPermission and RBACRoleCheck.

This allowed a more meta driven code that can also be used to generate the AzMan store through reflection as a post build event. One drawback of RBACPermission attribute is that it will depend on ContextBoundObject use of interception that can incurr some overhead. In that perspective one should be able to use CLR built-in PrinicpalPermission approach, though again it is role centric vs Permssion centric.

In later post I will describe further in details on the RBACPermission custom attribute, I may post an article on this, please comment if you think this was a valuable post and need further details on approach.

Few links :

msdn.microsoft.com/msdnmag/issues/03/11/AuthorizationManager/

msdn2.microsoft.com/en-us/library/system.security.permissions.principalpermission.aspx

Concept used include Custom Identity management in ASP.net Attribute based programming

Categories: 

RBAC requirements

Here is the summary of requirements from an RBAC .Net implementation:

1. Solution should support major requirements of NIST RBAC:
a) Subject Roles participation construct
b) Role hierarchy support
b) Permission / Operation construct
c) SSD support (Static separation of duty)
d) DSD support (Dynamic Separation of duty)
2. The solution should integrate seamlessly with .Net 2.0 Security packages, Principal, Permission , and ASP.Net Role Provider model.

3. The solution should utilize .Net attribute based programming to separate from a particular implementation of RBAC.

In above only 1c, and 1d are not directly supported through AzMan, but using the scripting extensibility supported by AzMan, it at least should be possible.
I will post something on this subject later.

Following nUnit test describe various usage scenario:

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;Test-App
using RBACAttributes;

namespace RBACAttributesTest
{
/// <summary>
/// Checks LeeT user for RBAC
/// </summary>
[TestFixture]
[RBACPermission(
AppName = "Test-App" , RolesAdvice = "DataOperators|Manager",TaskName="Patient management") ]
public class RBACTestForSid:ContextBoundObject
{
public RBACTestForSid()
{

Assert.IsTrue(this is ContextBoundObject);

}

System.Security.Principal.WindowsImpersonationContext _wicImpersonate = null;
[TestFixtureSetUp]
public void SetUp()
{
System.Security.Principal.GenericIdentity gi = new System.Security.Principal.GenericIdentity("ifti");
System.Threading.Thread.CurrentPrincipal = new RBACCustomPrincipal("Test-App", gi, true);

}

[TestFixtureTearDown]
public void TearDown()
{
}



[Test]
[RBACPermission(
PermissionName = "Permission To Add Patient")]
public void OpAddPatient()
{
Console.WriteLine("Add Patient");
Assert.IsTrue(true); //if it comes here the permission was given
}

//TODO, in NUNIT how to have a method test where failure would be a success, this is the case for LeeT user
/*
[Test]
[RBACPermission(
PermissionName = "Permission To Remove Patient")]
public void OpRemovePatient()
{
Console.WriteLine("Remove Patient");
Assert.IsTrue(true); //if it comes here the permission was given
}
* */

[Test]
public void ProgrammaticAccess()
{

Console.WriteLine("Programmatic Remove Patient");
Assert.IsTrue(RBACPermission.CheckAccess("Test-App", "add patient", System.Threading.Thread.CurrentPrincipal.Identity.Name, "RBACTest", "OpAddPatient"));
Assert.IsTrue(RBACPermission.CheckAccess("Test-App", "remove patient", System.Threading.Thread.CurrentPrincipal.Identity.Name, "RBACTest", "OpRemovePatient"));
Assert.IsTrue(RBACRoleCheck.IsUserInRole("Test-App", "Data entry supervisor"));
Assert.IsTrue(RBACRoleCheck.IsUserInRole("Test-App", "Data entry operator"));
Assert.IsTrue(RBACRoleCheck.IsUserInAnyRoles("Test-App", new string[] { "Data entry supervisor", "abcd", "xyz" }));
Assert.IsFalse(RBACRoleCheck.IsUserInAllRoles("Test-App", new string[] { "Data entry supervisor", "Data entry operator", "xyz" }));
Assert.IsTrue(RBACRoleCheck.IsUserInAllRoles("Test-App", new string[] { "Data entry supervisor", "Data entry operator" }));
Assert.IsTrue(System.Threading.Thread.CurrentPrincipal.IsInRole("Data entry supervisor"));
}

/// <summary>
/// Note PrinicpalPermission can be used without object being ContextBoundObject, so
/// this is a big plus whereever a more performance driven method check is needed,
/// unfortunately it does not check for permission, rather only role
/// </summary>
[Test]
[System.Security.Permissions.PrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Role = "Data entry supervisor")]
public void BuiltInNetCheck()
{
Assert.IsTrue(true);
}

//TODO, in NUNIT how to have a method test where failure would be a success,
/*
[Test]
[RBACRoleCheck("Data entry supervisor")]
public void RoleCheckForSupervisor()
{

Assert.IsTrue(true);
}
* */

[Test]
[RBACRoleCheck("Data entry operator")]
public void RoleCheckForOperator()
{

Assert.IsTrue(true);
}

[Test]
[RBACRoleCheck(new string[] {"Data entry supervisor","Data entry operator"}, RBACRoleCheck.CheckQualifier.All)]
public void RoleCheckForAny()
{

Assert.IsTrue(true);
}

//TODO, in NUNIT how to have a method test where failure would be a success, this is the case for LeeT user
/*
[Test]
[RBACRoleCheck(new string[] { "Data entry supervisor", "Data entry operator" }, RBACRoleCheck.CheckQualifier.All)]
public void RoleCheckForAll()
{

Assert.IsTrue(true);
}
* */

}
}

in above example, two roles
data entry operators
and
data entry supervisors
are used as example.
Two permissions are tested :
OpAddPatient
OpRemovePatient

Only data entry supervisor can remove patient.
Also, data entry supervisors inherit from data entry operators.



ASP.Net 2.0 Role Provider
To support Azman custom Sid a custom Role provider should be provided that
seamlessly support ASP.Net 2.0 role based access using custom attribute and PrincipalPermission API.

So we should be able to programmatically check roles :

if (!Roles.IsUserInRole("Data entry supervisor"))
{
this.Error.Text += "\r\nUser is not in Data entry supervisor role";
}

And declaratively :
[PrincipalPermission(SecurityAction.Demand, Role="Data entry supervisor")]

You may have noticed use of a non built-in attribute in nUnit test :
[RBACRoleCheck]

        [RBACRoleCheck(new string[] { "Data entry supervisor", "Data entry operator" }, RBACRoleCheck.CheckQualifier.All)]
public void RoleCheckForAll()
{

Assert.IsTrue(true);
}

This enable declarative check of All or Any test for roles participation.

In all cases if a check is asserted as false, a System.Security.SecurityException should be raised.

RBAC classes

Here is the class diagram of the implementation



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Recent comments

User login

About our advertising.

Atom Feed

developer.* Blogs also has an Atom feed, located at this url.

Click here for more information about Atom.

A Jolt Award Finalist
Software Creativity 2.0
Foreword by Tom DeMarco

Recent Posters

Based on most recent 60 days, sorted by # of posts and name.

Google
Web developer.*

Who's online

There are currently 0 users and 25 guests online.

Syndicate

Syndicate content
All views expressed by authors, bloggers, and commentors are their own and do not necessarily reflect the views of developer.* or its proprietors.
Click to read the Copyright Notice.

All content copyright ©2000-2005 by the individual specified authors (and where not specified, copyright by Read Media, LLC). Reprint or redistribute only with written permission from the author and/or developer.*.

www.developerdotstar.com