Enforce CRUD security by using Drools
leonvet Aug 26, 2009 9:40 AMFor a few days now i've been stuggling with an user case and i was wondering if anyone could give me some hints on how to solve it.
The end goal is to grant CRUD permissions to an entity (especially the 'read' permission) by using a drools rulebase, without any changes to ejbql query statements.
So far i've got an entity Department, annotated with @Restrict, an entitylistener in the orm.xml, a drools debugger class to see what objects are inserted into the working memory and a simple departmentList entityquery which returns all departments. Two users are registered, one with the role 'admin' and one with the 'user' role.
As a test i've defined a rule to grant read access to a Department:
rule "admins can read anything"
when
d : Department()
c : PermissionCheck( target == d, action == "read", granted == false )
Role( name == "admin" )
then
c.grant()
end
This rule works great, my admin user can execute the departmentList query and all Department entities are returned. My non-admin user get's an empty list. So far everything is fine.
Now i want to implement a very simple restriction for my non-admin user that he can read the 'Finance' department, but nothing else. ( In the real world application this would be something along the lines of user can see department if he's an employee of this department and ....) I've added this rule:
rule "user can see finance department"
when
d : Department( name == "Finance" )
c : PermissionCheck( target == d, action == "read", granted == false )
Role( name == "user" )
then
c.grant()
end
Now the non-admin user executes the departmentList query and nothing is returned. In the output of the drools debugger class i can see that the Finance department is inserted into the working memory ( it is also the first record in my department table ). The 'user can see finance department' rule is fired and access is granted. Great! This is what i need, but now the second department is added to the working memory and no matching rule is found, so the permissioncheck returns a NotAuthorized exception. This is also fine since the user is not allowed to read this department entity.
The problem with this is that the execution of the departmentList query is immediately halted and the query result is empty!
I know i can create a different departmentList statement, or use restrictions on the statement, but that is not my end goal. In the end there will be around 18 different user roles in this application ( finance, manager, employee, helpdesk, etc.. ) all with very different access to a whole host of different entities. I would really like to confine all crud security checks to a rulebase and only define crude ejbql statements ( like select all departments where customer = user.customer ) so the rules can filter the query results ( for example: "only show only departments that are descendants of the employee's department" ).
Is there any way i can accomplish this ? Any suggestion is appreciated.
Leon
The end goal is to grant CRUD permissions to an entity (especially the 'read' permission) by using a drools rulebase, without any changes to ejbql query statements.
So far i've got an entity Department, annotated with @Restrict, an entitylistener in the orm.xml, a drools debugger class to see what objects are inserted into the working memory and a simple departmentList entityquery which returns all departments. Two users are registered, one with the role 'admin' and one with the 'user' role.
As a test i've defined a rule to grant read access to a Department:
rule "admins can read anything"
when
d : Department()
c : PermissionCheck( target == d, action == "read", granted == false )
Role( name == "admin" )
then
c.grant()
end
This rule works great, my admin user can execute the departmentList query and all Department entities are returned. My non-admin user get's an empty list. So far everything is fine.
Now i want to implement a very simple restriction for my non-admin user that he can read the 'Finance' department, but nothing else. ( In the real world application this would be something along the lines of user can see department if he's an employee of this department and ....) I've added this rule:
rule "user can see finance department"
when
d : Department( name == "Finance" )
c : PermissionCheck( target == d, action == "read", granted == false )
Role( name == "user" )
then
c.grant()
end
Now the non-admin user executes the departmentList query and nothing is returned. In the output of the drools debugger class i can see that the Finance department is inserted into the working memory ( it is also the first record in my department table ). The 'user can see finance department' rule is fired and access is granted. Great! This is what i need, but now the second department is added to the working memory and no matching rule is found, so the permissioncheck returns a NotAuthorized exception. This is also fine since the user is not allowed to read this department entity.
The problem with this is that the execution of the departmentList query is immediately halted and the query result is empty!
I know i can create a different departmentList statement, or use restrictions on the statement, but that is not my end goal. In the end there will be around 18 different user roles in this application ( finance, manager, employee, helpdesk, etc.. ) all with very different access to a whole host of different entities. I would really like to confine all crud security checks to a rulebase and only define crude ejbql statements ( like select all departments where customer = user.customer ) so the rules can filter the query results ( for example: "only show only departments that are descendants of the employee's department" ).
Is there any way i can accomplish this ? Any suggestion is appreciated.
Leon