tags:

views:

141

answers:

2

One problem that I come across regularly and yet don't have a solution to is to restrict or permit access to specific entities in a system. Some companies (banks, for example) have very strict policies regarding which employees may access certain information. For example, an employee at a specific branch may access account information for customers of that specific branch but not from other branches. Also, banks that have branches in many countries may be subject to legal restrictions that restricts employees in other countries from accessing information about domestic customers.

Another example I've come across is a public website where users belong to a specific entity (such as a company) and may access information regarding that entity only and not other entities.

If the number of entities is small and fixed, this is not a problem. Simply specify domain groups in the active directory (if you're working in Microsoft environments, which is the case for me), add users to the groups and restrict access using IsInRole() for each entity. So if there is a company called ABC in the system I'd create a domain group called "Admins_ABC" or something like that and when a user tries to administer information about ABC, I'd make sure the user is a member of that group. This is not really the way the AD is intended to be used, but for a small number of entities I've found it reasonable.

The complexity increases when the number of entities change often and when the requirements become more detailed. I've seen security requirements that are similar to security in NTFS - some users (or groups of users) should be able to access some entities (files in NTFS) or groups of entities (the permissions that are set on directories in NTFS are propagated to it's children).

I try to avoid situations like these because they tend to be a nightmare to model and code and they usually become complex to administer, but the customers I work with often need solutions to this problem.

Like I said, I have never actually solved this problem in a good way. How would you go about modeling and developing a solution for this problem in a way that can be reused? Do you know of any general, proprietary solutions that can be used?

+1  A: 

Have you looked into the Code Access Security model that Microsoft created for the .NET framework? I have only looked at it on a few occasions myself, but the jist of it is that you can lock down certain objects and methods so that only users from internal networks can actually call that code. Or similarly, a method that does maintenance can only be called from the machine itself that the code is installed upon, preventing a third party from hacking a maintenance routine.

Wikipedia makes a nice summary of CAS:

Code Access Security (CAS), in the Microsoft .NET framework, is Microsoft's solution to prevent untrusted code from performing privileged actions. When the CLR loads an assembly it will obtain evidence for the assembly and use this to identify the code group that the assembly belongs to. A code group contains a permission set (one or more permissions). Code that performs a privileged action will perform a code access demand which will cause the CLR to walk up the call stack and examine the permission set granted to the assembly of each method in the call stack. The code groups and permission sets are determined by the administrator of the machine who defines the security policy.

This article from 15 Seconds has a nice and quick overview on how to get things going.

Dillie-O
Yes, I am aware of Code Access Security. However, CAS is a sandbox model and it is not what I'm looking for.
Karl
+2  A: 

I've beat my head against this wall on several occasions.

The best solution I've come to was to model everything in a tree hierarchy, where every domain class is an branch in the tree, and instances are leaves of that branch. Leaves can have veins if you need to secure parts of instances. Each branch has its own assigned actions (such as "Read", "Write", "Delete", "Publish"). Use the same hierarchy for security but the root then becomes a user or a group. You end up with a structure like:

<domain> Project
|- <class> Person
| |- <instance> John
| |- <instance> Mary
|- <class> FormX
| |- <instance> John's Leave Form
...

and to apply security you may have a group named Administrators who can do stuff with people:

<group> Administrators
|- <class> Person: actions (Read, Create, Update, Suspend)

and an office admin who can process forms and make new people:

<group> Office Administrator
|- <class> Person: actions (Create)
|- <class> FormX: actions (Approve, Deny)

and then John can do stuff with his own profile:

<user> John
|- <class> Person
| |- <instance> John: actions (Edit)

When I implemented this structure it was using C# and SQL Server 2000 so I was able to use the XML schema data type and perform security queries against the database or [as more often the case] merge a person's security profile into a single tree to determine what rights someone has to an instance, class, or other (I had <group>s - not security groups - in the domain above class for ease of maintenance).

Its also important to include - though I did not illustrate it - that each action was a permission, not a boolean, where the permission values were { Allow, None, Deny } with Allow granting access to that verb except when explicitly denied, None neither allowing nor denying, and Deny preventing access no matter what.

An advantage you gain from this structure is that you can add other types of branches into it, such as a data driven taxonomy, and still use the same API.

In my specific implementation I added custom metadata attributes to methods and properties and I had to invoke a SecurityManager.Test method in each "secured" function as a final layer of authorization (SecurityManager.Test was normally invoked to determine whether to show or hide pieces of a form, and determine which buttons were visible in the UI). Now that I am aware of it if I ever have to implement the same thing again, I'll use PostSharp to inject security tests into my domain model.

cfeduke
Yes, that's close to how I've implemented this as well, although your implementation seems more organized and complete. I had an idea to use attributes instead of what you call SecurityManager.Test(), but the PostSharp-idea is great! Thanks, you've helped a lot!
Karl