On Nov 17, 2009, at 1:01 AM, Quintin Beukes wrote:

I think what I'm going to do is add another level of abstraction
around roles in my database.

Where I now have
Operators->Roles

I will have
Operators->Roles->ContainerRoles

So each module defines it's roles and has a OneToMany on
ContainerRoles. ContainerRoles will then have a OneToOne mapping to a
role in the deployment descriptor and my SQLLoginModule will then do
another LEFT JOIN on ContainerRoles which would then become the
GeronimoGroupPrincipals for the subject.

This seems like a reasonable solution. I can't think of a better one that doesn't involve writing a whole new security system.

I'm not sure it's immediately relevant to your situation but, if you are not already familiar with the ideas, you might be interested in investigating hierarchical role-base access control (RBAC). I spent some time working on an implementation (soter at codehaus) but didn't get it integrated into geronimo.

thanks
david jencks


Quintin Beukes



On Tue, Nov 17, 2009 at 10:25 AM, Quintin Beukes <[email protected] > wrote:
This is my situation.

I have the server, which has the roles/users and EJB security with
@RolesAllowed. This is container managed and the important part, as
it's absolutely crucial that you can't execute what you're not allowed
to. This works fine.

Further it's a modular system. You load the modules you want and they
work together to form a system. Each module has it's own roles.

For example, we have the platform (core) module which defines
"Standard User" and "Admin". The "Admin" has access to almost
everything as each module lists it explicitly to be allowed to do
almost everything (just a few things like those for services which it
can't do). Then the personnel module which defines "Personnel Admin"
and "Personnel User". And for arguments sake on more called "Lamp"
with say, "Lamp Room" and some others. So Personnel module has no
concept of "Lamp Room". In the Lamp EJB when I do the mappings I here
list that the "Lamp Room" group maps to "Lamp Room", "Personnel User"
and "Standard User". So each module down the hierarchy lists the roles
upwards which it maps to, like in this case "Lamp Room" users need
read access to personnel as well.

This is all fine for the server, as it works. The problem is on the
client. I need a way for this information to be retrieved from the
server. I am hoping to get the information as the server understands
it to reduce maintenance and thus avoid potential bugs. If I have to
start maintaining multiple hard coded lists of permissions I'm just
looking for trouble. Especially when another developer has to start
working on this code base, which is the case as I usually don't do the
maintenance.

The reason I need it client side is to construct the UI. The main
terminal GUI is a desktop application and it has to
enable/disable/hide/show actions based on the user's roles. Also,
since it's modular I have exposed certain services, like for
navigation. Each module broadcasts only it's actions, and the
navigation module automatically takes care of authorization using
annotations on the action's class. The typical modular system...
trying to modularize everything and on duplication.

Is there perhaps a way I can tell the server how to do the role
mappings programmatically? So, instead of listing it in a deployment
descriptor it's listed in the database and when one of my Singleton
beans load I can configure the role mappings?

Quintin Beukes



On Mon, Nov 16, 2009 at 10:37 PM, David Jencks <[email protected] > wrote:

On Nov 16, 2009, at 10:39 AM, Quintin Beukes wrote:

Even if it means quite a bit of code. I seriously need a way to
determine the roles. It's either this or a massive overhaul on our
user/group/role system where the whole system is already
standing at 80000 lines of code. Changing the auth structure at this
point would postpone the release too much.

This is the last thing standing between me and a phase 1 release. Any
suggestions would thus be greatly appreciated.

I've also wanted a

Collection<String> getUserRoles()

 method but there isn't one. About the only thing you can do is

List<String> allRoles = //hard-code or read from a property file???
List<String> userRoles = new ArrayList<String>();
for (String role: allRoles) {
 if (context.isUserInRole(role)) {
   userRoles.add(role);
 }
}

I'm curious why you need this much information for this kind of partially
app managed security.  Maybe there's another way to approach this.

One possibility is to add more container managed security -- a whole
additional kind of permission -- to your setup. You can write security deployers to add more role-permission mappings to the security system and then at runtime your app can test with accessControlContext.implies(new MySpecialPermission(info)). This may well not be enough info, but if this
sounds remotely plausible let me know....

hope this helps
david jencks




Quintin Beukes



On Mon, Nov 16, 2009 at 8:04 PM, Quintin Beukes <[email protected] >
wrote:

Oh yes :<

I was so focussed on my initial problem that I forgot about the
workings of isCallerInRole(). You have to do @DeclareRoles({..}) at
the class level. I actually do this everywhere I call
isCallerInRole(). It was just in this case where I'm trying to
determine the call's roles. The subject wasn't working (I now know
it's obvious, as a role isn't a principal), so I tried to do
isCallerInRole() without using it properly.

I have a big problem though.

Is there any way at all to get a list of roles for a user as mapped in the deployment descriptor? Even if I have to query the Geronimo API. Portability when it comes to security is really not a big issue for me as I feel JavaEE's security is vague in any case. Besides, where ever
I break portability I do so through interfaces and implementations
with some "container validation". So if someone following me tries to port he'll get a "friendly" message stating he needs to make his own
implementation.

Quintin Beukes



On Mon, Nov 16, 2009 at 7:29 PM, David Jencks <[email protected] >
wrote:

Hi Quintin,

On Nov 16, 2009, at 8:41 AM, Quintin Beukes wrote:

Hey,

I basically have a bunch of roles which should each be mapped to
different combinations of a user's "GroupPrincipals". Something like
this:

   <sec:role role-name="Lamp Room">
     <sec:principal
class
= "org .apache .geronimo.security.realm.providers.GeronimoGroupPrincipal"
name="Lamp Room"/>
   </sec:role>
   <sec:role role-name="VDS User">
     <sec:principal
class
= "org .apache .geronimo.security.realm.providers.GeronimoGroupPrincipal"
name="Lamp Room"/>
   </sec:role>
   <sec:role role-name="Personnel User">
     <sec:principal
class
= "org .apache .geronimo.security.realm.providers.GeronimoGroupPrincipal"
name="Lamp Room"/>
   </sec:role>

This means that named roles are all assigned to a user of group "Lamp
Room".

Though doing the following I don't see these "virtual roles", only the
actual group.
 Subject subject = ContextManager.getCurrentCaller();
 Set<Principal> principals = subject.getPrincipals();

roles are just names, not principals, so there's no way you'll see them
in
the Subject.  Here's how it works, in PolicyContextGeneric:

1. the principal-role map specified above is fed in.
2. the role-permission map specified by the DD or annotations is fed in 3. these are combined to form a principal-permission map as the app
starts
up
4. when you test a permission (either through container access control
or an
isUserInRole/isCallerInRole call) we run through the Subject's
principals,
get the PermissionCollection for that principal, and see if it implies
the
permission desired.

One thing to note about this is that geronimo needs to know about the
role
and permission you're going to check. So the role has to be declared
somewhere.  I'm less sure about the role-ref permission...
for web apps there is an implicit role-ref permission set up mapping the role to itself for any role without an explicit role-ref. I don't
recall
how ejbs work, I kinda think that you have to declare all the roles you
are
going to test with a role-ref.


I can see how this would be the case, though the following must
definitely work: isCallerInRole("Personnel Admin") or EVEN
isCallerInRole("Lamp Room"). They all return false.

If I have a method annotated with @RolesAllowed({"Personnel User"}),
then GeronimoSecurityService.isCallerAuthorized(Method method,
InterfaceType typee) return TRUE.
Though, GeronimoSecurityService.isCallerInRole(String role) returns
FALSE when I query isCallerInRole("Personnel User").

I think this might support my idea that you have to explicitly set up a
role-ref for any role you mean to test in an ejb.

I assume somewhere the AccessControlContext isn't populated correctly? I'm not really sure how this should work, so if someone can tell me
how this all fits together I can have a look.


Let me know if the above doesn't answer your questions

thanks
david jencks

Quintin Beukes







Reply via email to