Fake binary trees
... rants, ramblings and occasional good idea ...

Access control based security

Natural question to ask after previous post is: that's all fine and dandy but how do you combine this with access control list (ACL) based security?

First, let's explain the issue here: What I refer to as 'ACL based security' is defining permissions (access rights) for individual resources, similar to the way operating systems allow access to file system. E.g. user 'xy' can see all tasks for projects he manages, but also all other tasks in other projects where their managers have allowed access to 'xy', or tasks which are assigned to 'xy'. This changes our imaginary security API from HasPermission(user, permission) to HasPermissionFor(user, permission, object)

Although security is usually not considered a business logic, the line starts to get blurry here. In my opinion, this is both a business and infrastructure concept.

One possible solution, which unfortunatelly can be seen too often, is to retrieve data as usual and then throw away resources which don't match the permissions. This approach fails miserably in many aspects: performance, filtering, paging, etc.

I am not sure if it is even possible to create a 'one size fits all' solution for this problem. However, in most systems that I had to deal with, following solution was able to get me quite far.

Note: I presume that the infrastructure is already set up: additional database tables store ACL entries which define who is allowed or denied access to individual resources, so that queries which retrieve items from the database can join on these tables. This is not a trivial thing and can become quite complex, especially when you take into account resource hierarchies (e.g. project-task), but it is out of scope of this post.

Anyway, suppose that we have ITaskManagementService which exposes following method:

[RequiresPermission(Permission.Edit)]
void GetTasks( ... parameters...)
{
    // m_taskRepository is an instance of ISecureRepository<T>
    m_taskRepository.GetAll(); 
}

Service has SecurityInterceptor implemented through Windsor/DP2, which checks for RequiresPermission attribute and do something like:

class SecurityInterceptor : IMethodInterceptor
{
    public object Intercept(IMethodInvocation invocation, params object[] args)
    {
            CallContext[Context.Security] = new SecurityContext(CurrentUser, attr.Permission);         
            return invocation.Proceed(args);
    }
}

than in the SecureRepository implementation, permissions are added to the query:

public IList<T> GetAll()
{
    ICriteria criteria = BuildCriteria();
    return criteria.List<T>();
}

public void BuildCriteria<T>()
{
    ICriteria criteria = Session.CreateCriteria(typeof(T));
    SecurityContext security = CallContext[Context.Security];
    // now we modify criteria to join entity tables with ACL tables...
    AddPermissions(criteria, security.UserId, security.RequiredPermissions);
}

This will make sure that GetAll() method returns only those tasks for which the caller has sufficient permissions. The drawback of the solution is that it only works if the resources and permissions are stored in tables in the same database so you can join them, but this usually isn't an issue for most small to medium solution.

Posted at 18:01 on February 6, 2008
Categories: .NET | Software Design   E-mail | del.icio.us | Permalink | Comments (0) | Post RSSRSS comment feed

Implementing security (and other cross-cutting concerns) through AOP

A common problem with implementing security is that you end up with bunch of repeated code blocks which check the current user's permissions and then allow or disallow the execution of some method. Example:

public class OrderManagementService : IOrderManagementService
{
    public Guid CreateOrder(string orderCode)
    {   
        if(!CallContext.CurrentUser.HasPermission(Permissions.CanCreateOrder))
        {
            throw new SecurityException("Only users with CanCreateOrder permission can create an order.");
        }

        Order order = new Order(orderCode);
        order.Save(order); // ActiveRecord-like implementation
        return order.Id;
    }
}

The problem with this approach is that you have to implement the check in every method which requires some combination of permissions. While this is not overly hard to do, it becomes a maintenance hell as the number of such methods grows. Also, if you want to change the behavior in case of missing permissions you have to modify all those functions. Of course, you can encapsulate it in some common utility method, like this:

    ...
    if(!CallContext.CurrentUser.HasPermission(Permissions.CanCreateOrder))
    {
        HandleMissingPermissions("Only users with CanCreateOrder permission can create an order.");
    }
    ...

This is also not perfect: If you decide that you need more context info in the utility method (e.g. required permissions or method name) you have to modify it:

    ...
    if(!CallContext.CurrentUser.HasPermission(Permissions.CanCreateOrder))
    {
        HandleMissingPermissions("CreateOrder", Permissions.Admin, "Only users with CanCreateOrder permission can create an order.");
    }
    ...

Now you have to modify all calls to HandleMissingPermissions method, etc.

The issue with application security is that it is a cross-cutting concern: it applies to all parts of system and not to a specific context, therefore, it doesn't make sense to implement it at each point where it is needed. In other words it is an application aspect (in AOP sense), and it is often best implemented in such manner.

There are many ways to implement AOP in .NET world: (Aspect#, NAspect), IL weaving (PostSharp) etc. In my opinion, one of the easiest is using interception features which are provided by some IOC container (e.g. Windsor and Spring.NET have it, StructureMap added it recently). In this example, I will use Windsor, because I am more familiar with it than with the others. For those who somehow missed it, Windsor is a quite popular IOC library, which is a part of Castle, an open source set of tools for easier development of enterprise and web applications.

So, here is how we are going to implement security:

  • We are going to define security requirements for each method using attributes
  • Instances of the target service (IOrderManagementService) will be retreived through the IOC container
  • IOC container will inject the security interceptors
  • Interceptor will check whether the method caller has required permissions


Our OrderManagementService class will now look like this:

[Interceptor(typeof(SecurityInterceptor))]
public class OrderManagementService : IOrderManagementService
{
    [RequiredPermission(Permissions.CanCreateOrder)]
    public virtual Guid CreateOrder(string orderCode)
    {   
        Order order = new Order(orderCode);
        order.Save(order); // ActiveRecord-like implementation
        return order.Id;
    }
}

OrderManagementService class is decorated with [Interceptor] attribute which defines the interceptor class which will be used to wrap the methods. You can define multiple interceptor classes, but usually it is better to do this in configuration file (see attached sample) than directly in the code, because you can switch the interceptors on/off without recompiling the code. This can be useful for debugging purposes or trouble-shooting.

Back to the implementation: security related logic is not checked in CreateOrder method anymore. Instead, SecurityInterceptor reads metadata for each method which is executed and according to RequiredPermission attribute of the method and permissions granted to the current user decides whether the method should be executed or not. Here is the implementation of the SecurityInterceptor:

class SecurityInterceptor : IMethodInterceptor
{
    public object Intercept(IMethodInvocation invocation, params object[] args)
    {
        MethodInfo method = invocation.Method;
        if(NeedsAuthorization(method) && GetRequiredPermission(method) != Context.Caller.Permission)
        {
            string message = string.Format("Method {0} requires {0} permission",
                                            method.Name,
                                            GetRequiredPermission(method));
            throw new SecurityException(message);           
        }

        return invocation.Proceed(args);
    }

    private bool NeedsAuthorization(MethodInfo method)
    {
        return method.IsDefined(typeof(RequiredPermission), true);   
    }

    private Permission GetRequiredPermission(MethodInfo method)
    {
         RequiredPermission attribute = (RequiredPermission)method.GetCustomAttributes(typeof(RequiredPermission), false)[0];
        return attribute.Permission;
    }
}

The only thing left to be done is to modify the client code to retrieve the IOrderManagementService instance via IOC container and call the method:

private void OnCreateOrderClicked(object sender, EventArgs e)
{
    // caller permissions have already been set
    IOrderManagementService svc = m_container.Resolve<IOrderManagementService>();   
    svc.CreateOrder("#ord-1-01");
}

This covers all the interesting parts of such implementation. Of course, in real-life scenarios this is not enough. The sample code is a bit more elaborated: you can define custom message for every RequiredPermission attribute instance, permissions can be combined etc.

The same approach can be used for other cross-cutting services, like logging and transaction handling.

You can download the sample here:  AopSecurity.zip (123.55 kb)

Posted at 12:31 on February 4, 2008
Categories: Castle.Net | .NET | AOP   E-mail | del.icio.us | Permalink | Comments (0) | Post RSSRSS comment feed

Otis 0.2 Released

I have just uploaded version 0.2 of Otis library. It supports a few handy features: aggregate functions, simplified string expressions and projection mappings.

It took more time than I expected, mostly due to lots of work on my dayjob and resulting lack of free time, but now it's done. It is now quite usable for most mapping scenarios. I hope you'll find it useful.

Posted at 11:12 on January 28, 2008
Categories: Otis   E-mail | del.icio.us | Permalink | Comments (0) | Post RSSRSS comment feed

Yet another blog, yet another open source project

Who needs one more blog, you might ask, and i wouldn't be able to provide a good answer.

I decided to stick a toe in blog waters mostly to have a place where I can post programming-oriented reminders to myself, and hopefully to share some useful tips/code with other people.

Anyway, it coincided with the public release of Otis, my pet project, so this is also an announcement for yet another open-source project of questionable future. Otis is an open-source .NET object mapper library and you can read (and discuss) more about it on its homepage. I surely hope that some of people who somehow manage to find it in the sea of other projects will find it useful.

Posted at 18:01 on November 23, 2007
Categories: Otis   E-mail | del.icio.us | Permalink | Comments (10) | Post RSSRSS comment feed