Permission Implementation

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Permission Implementation

Scott Ryan-3
Has anyone published a sample implementation of a permission scheme  
with tables and code?   There is a fairly complex example for other  
security frameworks including heirarchical roles and bit based  
permissioning.

I have a need to have multiple levels of permissions with the ability  
to allow or deny permissions at any level and to support inheritance.

For example I may have a heirarchy of roles:

Admin
Manager
User

Permissions for Admin should include an aggregate of permissions for  
all 3 roles.  Also how to handle denies?  I assume that denies  
encountered while scanning from user to manager to admin should be  
enforced

If on my application side i have a heirarchy as well:

Domain
Project
Task

I would like to be able to aggregate and handle grants and denies  
properly.   In reading the Shiro documentation and any articles I  
could find the Permission side is left up to the user to implement but  
I can't find any examples to guide me.

Thanks



Scott Ryan
[hidden email]



Reply | Threaded
Open this post in threaded view
|

Re: Permission Implementation

Les Hazlewood-2
Hi Scott,

The samples/spring and samples/spring-hibernate examples both provide
these in the BootstrapDataPopulator beans.  The Spring/Hibernate
sample uses JPA annotations to specify these tables/mappings.

On Mon, Aug 31, 2009 at 12:41 PM, Scott Ryan<[hidden email]> wrote:
> Has anyone published a sample implementation of a permission scheme with
> tables and code?   There is a fairly complex example for other security
> frameworks including heirarchical roles and bit based permissioning.

You're right, there aren't any more complicated examples beyond the
existing samples because groups/roles/permissions modeling is _very_
environment/application specific - everyone does it their own way.
Shiro's primary focus has been on creating a security framework that
is powerful and flexible enough to work with any application, and not
necessarily on recommending data models to support application
frameworks.

But that's not to say what you're asking isn't valuable.  A decent
number of people have asked for similar things.  I think I'll have to
come up with a reasonable complex data model that could support most
deployments (sticking to the 80/20 rule - I'm sure there are 20%
fringe cases which I wouldn't model).

But let's talk about your specific needs here, and hopefully it will
give you ideas how to use Shiro to support them.

> Also how to handle denies?  I assume that denies encountered while
> scanning from user to manager to admin should be enforced

Your Realm implementation supports grant vs deny logic in the
isPermitted or hasRole methods - it is up to you exactly what happens.
 Most people go with a grant-only policy for simplicity.  A Subject
would never never have permissions to do anything unless the
isPermitted implementation returns true for a particular user.

Note that most of Shiro's default Realm implementations extend
AuthorizingRealm and do these checks for you automatically, but for
more complicated enterprise applications, you'll probably want to
implement or override all of those checks yourself to delegate to an
internal data model.

> I have a need to have multiple levels of permissions with the ability to
> allow or deny permissions at any level and to support inheritance.
>
> For example I may have a heirarchy of roles:
>
> Admin
> Manager
> User

I personally don't like to do this - it makes the data model
unnecessarily complex IMO.  To me, a role is nothing more than a named
set of permissions.  Multiple roles may or may not overlap their
permissions set, and I write my application to automatically assign
whatever roles necessary depending on the type of user.

For example, if in a UI, I create a new 'admin' user, then my code
would automatically assign all 3 roles to the user to achieve your
desired effect:

Role adminRole = getRole("admin");
Role managerRole = getRole("manager");
Role userRole = getRole("user");

user.addRole(userRole);
user.addRole(managerRole);
user.addRole(adminRole);

When you don't model things this way, you have to go through the major
headache of grant vs deny problems - "I've assigned all these
permissions to this particular role, but in this one case, I want to
remove permission X for this particular child role/user".

Ouch - very difficult to manage in code and a major frustration.  Your
head starts to spin with inclusion/exclusion policies.

Its far better to ignore exclusionary policies and just assign
permissions to roles and assign roles to users and/or groups.  I
personally don't have any recommendations about 'denies' - my systems
are always grant-based specifically to avoid the many problems and
large confusion arising from exclusionary policies.

My general rule of thumb:

A Role is a named Set of permissons
a User 'has' a Set of one or more Roles
a User 'has' a Set of permissions for that-user-only permissions (not
shared with anyone else - otherwise they'd go in a Role)
A Group is a named Set of 'Party' objects (a User is a Party and a
Group is a Party - allowing for instances of both to exist in
hierarchical Party trees)

If anyone has any other ideas, I'd love to hear them.  Especially if
you've had to deal with exclusionary policies and how you made that
work in Shiro.  I personally have avoided that like the plague ;)

Regards,

Les
Reply | Threaded
Open this post in threaded view
|

Re: Permission Implementation

Scott Ryan-3
I did look at the code however it was too simple for my needs.  The  
system I developed has 10's of thousands of users and 1000's of  
permissions and managing them as Strings would be difficult as would  
be creating Roles or Groups for every possible combination.  One  
scenario might be as follows:


1. Users have permission across the system such as the ability to use  
IM or email
2. Users can join projects dynamically by signing up or being invited.
3. Project owners control capabilities within the projects for all  
users for example one project might allow IM or not deny it if the  
user already has that capability  and another project might not allow  
any users to IM even if they have it at a higher level.  Once a deny  
is hit the permission is denied but if it is not allowed or is allowed  
and not denied the permission is allowed.  The query never goes lower  
than the requesting level.

This is where the deny capability becomes important.  It would be  
prohibitive to assign the IM capability to each user in each project  
as they sign up and the data would grow too large to query  
efficiently.   For legal reasons I might want to deny capability to IM  
for a project for even those that have it across the system.

The most efficient way I have found to do this is to grant the IM  
capability at the highest level and then if required (very seldom) use  
a deny to make sure no one can IM from a project.  The hierarchy I am  
dealing with is much more complex than this with potentially 10 levels  
of permission hierarchy but the idea still holds true.  In the past I  
have done this in LDAP and bit masks to get the performance i needed  
but am trying to implement in Shiro to test it out in a new grails  
application.


Scott Ryan
[hidden email]



On Aug 31, 2009, at 11:44 AM, Les Hazlewood wrote:

> Hi Scott,
>
> The samples/spring and samples/spring-hibernate examples both provide
> these in the BootstrapDataPopulator beans.  The Spring/Hibernate
> sample uses JPA annotations to specify these tables/mappings.
>
> On Mon, Aug 31, 2009 at 12:41 PM, Scott Ryan<[hidden email]>  
> wrote:
>> Has anyone published a sample implementation of a permission scheme  
>> with
>> tables and code?   There is a fairly complex example for other  
>> security
>> frameworks including heirarchical roles and bit based permissioning.
>
> You're right, there aren't any more complicated examples beyond the
> existing samples because groups/roles/permissions modeling is _very_
> environment/application specific - everyone does it their own way.
> Shiro's primary focus has been on creating a security framework that
> is powerful and flexible enough to work with any application, and not
> necessarily on recommending data models to support application
> frameworks.
>
> But that's not to say what you're asking isn't valuable.  A decent
> number of people have asked for similar things.  I think I'll have to
> come up with a reasonable complex data model that could support most
> deployments (sticking to the 80/20 rule - I'm sure there are 20%
> fringe cases which I wouldn't model).
>
> But let's talk about your specific needs here, and hopefully it will
> give you ideas how to use Shiro to support them.
>
>> Also how to handle denies?  I assume that denies encountered while
>> scanning from user to manager to admin should be enforced
>
> Your Realm implementation supports grant vs deny logic in the
> isPermitted or hasRole methods - it is up to you exactly what happens.
> Most people go with a grant-only policy for simplicity.  A Subject
> would never never have permissions to do anything unless the
> isPermitted implementation returns true for a particular user.
>
> Note that most of Shiro's default Realm implementations extend
> AuthorizingRealm and do these checks for you automatically, but for
> more complicated enterprise applications, you'll probably want to
> implement or override all of those checks yourself to delegate to an
> internal data model.
>
>> I have a need to have multiple levels of permissions with the  
>> ability to
>> allow or deny permissions at any level and to support inheritance.
>>
>> For example I may have a heirarchy of roles:
>>
>> Admin
>> Manager
>> User
>
> I personally don't like to do this - it makes the data model
> unnecessarily complex IMO.  To me, a role is nothing more than a named
> set of permissions.  Multiple roles may or may not overlap their
> permissions set, and I write my application to automatically assign
> whatever roles necessary depending on the type of user.
>
> For example, if in a UI, I create a new 'admin' user, then my code
> would automatically assign all 3 roles to the user to achieve your
> desired effect:
>
> Role adminRole = getRole("admin");
> Role managerRole = getRole("manager");
> Role userRole = getRole("user");
>
> user.addRole(userRole);
> user.addRole(managerRole);
> user.addRole(adminRole);
>
> When you don't model things this way, you have to go through the major
> headache of grant vs deny problems - "I've assigned all these
> permissions to this particular role, but in this one case, I want to
> remove permission X for this particular child role/user".
>
> Ouch - very difficult to manage in code and a major frustration.  Your
> head starts to spin with inclusion/exclusion policies.
>
> Its far better to ignore exclusionary policies and just assign
> permissions to roles and assign roles to users and/or groups.  I
> personally don't have any recommendations about 'denies' - my systems
> are always grant-based specifically to avoid the many problems and
> large confusion arising from exclusionary policies.
>
> My general rule of thumb:
>
> A Role is a named Set of permissons
> a User 'has' a Set of one or more Roles
> a User 'has' a Set of permissions for that-user-only permissions (not
> shared with anyone else - otherwise they'd go in a Role)
> A Group is a named Set of 'Party' objects (a User is a Party and a
> Group is a Party - allowing for instances of both to exist in
> hierarchical Party trees)
>
> If anyone has any other ideas, I'd love to hear them.  Especially if
> you've had to deal with exclusionary policies and how you made that
> work in Shiro.  I personally have avoided that like the plague ;)
>
> Regards,
>
> Les