Los Techies : Blogs about software and anything tech!

How To? Highly Complex Query Generating Based On Security Needs


I have the following object model:

 image

An Office belongs to one Office Group. An Office also belongs to one Office Region. There is no relationship between Office Group and Office Region. They are two separate groupings for various reasons. A Counselor belongs to one Office. A Veteran is assigned to one Office.

I need to implement the following security rules for a Counselor looking at Veterans, starting with “deny access to all Veteran records, unless any of the following are true”:

  1. If a Counselor is an Administrator (a role of the Counselor), that Counselor can see all Veteran records
  2. A Counselor can see any Veteran that has no current Office assignment
  3. A Counselor can see Veterans that are assigned to an Office within the Counselor’s Office Group
  4. If a Counselor belongs to a “Regional Office”, that Counselor can see Veterans that are assigned to that Region
  5. … a few others in similar fashion …

I also need to implement the following around the above rules:

  1. When a Counselor searches for Veterans, they are only allowed to see search results that meet the above criteria
  2. When a Counselor views the detail of a Veteran, they are only allowed to see the the Veteran if the above criteria is met. This includes, if a Counselor tries to manually load a Veteran (manually type in url “id=1234”)
    1. … and the Counselor is not allowed to see the Veteran, show a “Not Authorized” message
    2. … and the Vet does not exist, show a “Vet Does Not Exist” message

so…

how do you create a search process around a security need like this? How do you go about creating a very complex rule system to determine which Veterans the Counselor can see? In my ideal world, I’d have some way of checking this security need against the search results and against an individual veteran record, without duplicating the code or logic for that check anywhere… is this a realistic expectation? What “standard” security implementations are out there, that would help me resolve my needs?

This is being done in C# in an ASP.NET Webforms app, using NHibernate for our ORM. I don’t expect NHibernate to be able to solve this problem for us, but if it can, that’s even better. And, I do expect to be able to write some sort of Unit or Integration tests around whatever the process is.

Any advice or help is appreciated.

Kick It on DotNetKicks.com
Posted Jun 25 2009, 04:26 PM by derick.bailey

Comments

Tuna Toksoz wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 4:51 PM

In case you haven't seen Rhino.Security

ayende.com/.../Rhino-Security-Overview-Part-I.aspx

I am not sure if can do exactly what you want, but it is worth looking.

DotNetShoutout wrote How To? Highly Complex Query Generating Based On Security Needs - Derick Bailey - Los Techies
on 06-25-2009 5:00 PM

Thank you for submitting this cool story - Trackback from DotNetShoutout

derick.bailey wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 5:09 PM

@Tuna,

Thanks. I spent the last 30 minutes trying to read up on it. It seems fairly complex, off-hand, but it certainly looks like it is worth diving into, to see if it can help.

Gilligan wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 5:15 PM

We have similar complexity in parts of our system, like only retail members can see these items but everyone can see these other items.

I used Rhino security and put it in a separate bounded context. Rhino security can attach security criteria to any query. It also has the ability to relate permissions to a specific entity. So I created a set of security listeners that represent my security rules. The listeners listen to appropriate events and apply the needed security rules. Example for Rule #4. I would create listeners for the following events: Veteran added to region, veteran removed from region, Counselor added to Regional Office, and Counselor removed from regional office. When any of these events occurs the listener will add/remove the appropriate permissions for the Counselor/Veteran pair. Rhino Security handles everything else.

derick.bailey wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 5:22 PM

@Gilligan,

so what you're saying is that the permission would be stored in a table, to say "this couselor (id x) can see this veteran (id y)" and then at the time the check needs to be made, it would look at that cached permission list? is that close to what you're saying Rhino.Security does?

that's certainly a different concept than what I was trying to do, but is sparking some interesting thoughts in the back of my head... definately makes me want to look at Rhino Security further.

Gilligan wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 5:51 PM

Exactly. Rhino Security Permissions have three "dimensions" : User/User Groups, Operations (which are hierarchal), and optionally Entities/Entity Groups.

This allows us to break any security rule down into a simple "this user/group either can or cannot perform these operations on this entity/entity group". Rhino Security handles the aggregation of permissions (eg  a user is a member of a group but also has its own permissions for an operation) automatically.

Trust me once you implement Rhino Security you will never look back and you will wonder how you ever managed with only Asp.Net's role system before.

Adam Tybor wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 9:23 PM

+1 to Rhino Security.  The really cool part is how it transparently attaches to your domain then applies the necessary nhibernate detached criteria so filtering can happen in the query at the db level.  No more client side filtering and applying rules on huge result sets!

MIke wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-25-2009 11:19 PM

I wonder if you can take advantage of NHibernate Filters here and attach a security to the session at runtime to get let NH do the heavy lifting for you.

Might be simpler if this is the only place in your app you have encountered this

Arjan’s World » LINKBLOG for June 26, 2009 wrote Arjan’s World » LINKBLOG for June 26, 2009
on 06-26-2009 4:17 PM

Pingback from  Arjan’s World    » LINKBLOG for June 26, 2009

JC Grubbs wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-28-2009 6:24 PM

What about just building a set of composable methods that expose IQueryable<T> and then building up a query based on the current context's security concerns.  As you chain these methods together the query gets more and more limiting.  It's not a very "slick" way of doing it but the composability of IQueryable is extremely powerful.

Doug Ferguson wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 06-30-2009 1:52 PM

You might consider using a collection of specification patterns (Evans).  

Given the fact that you need to see the difference between "not-authorized" and  "does not exist", you may want to pull the releveant records for a vet even if the Conselor can't have access to the record.  

Then, you can run the results through a Specification rule, or a series of them, to determine if the conselor has access to the particular record.  

If not data is returned from the query, you know the record does not exist.  If a record IS returned, but the combination of the conselor and the vet fail the specification rule, you can return "not-authorized."

Here's a link to a specification implementation using generics.  I found it helpful and modified it to accept two objects.  You could pass in your conselor and the vet dto's.  

devlicio.us/.../the-specification-pattern.aspx

This may or may not work from a performance standpoint depending upon how many records are being returned/evaluated.  

dot net coder wrote re: How To? Highly Complex Query Generating Based On Security Needs
on 07-22-2009 8:33 PM

For Rhino Security

1.Where and how in the app life cycle(at which layer )  , do we "set" the

security keys for the entities ?

n does setting the security keys for entities inserts a record in the

EntityReferences (security) table ??

2.How do u bind entities from application domain (or application

tables ) with the rhino security using IInformation Extractor ? and

how and in which table of the rhino schema, these links shown.Permissions are to be added for entities as

enity group using permissions builder service using two overloads

.On(EntityGroup) and  .On<Entity>(Entity)

3.Please provide more documenation on the usage n implementation of

security tables :

a) Entity References (security)

b) EntityReferencesToEntityGroups

c) Use of "Oneverything"

Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems