Dynamic Role Hierarchy in Spring Security - dynamic

I can't believe all I find to define role hierarchies is some strange .xml notation of ">" assignments. There has to be a way to create a RoleHierarchy object from a database defined role hierarchy.. ?!
I'm thinking of a table that has the columns:
role_id
child_role_id
defining a many-to-many relationship between Role and Role saying: which role has which children? I think I'd prefer children over parents as that's the way the hierarchy is set up in those .xml files: ADMIN > USER, USER > VISITOR.
(This by the way makes me wonder if the standard implementation also supports things like ADMIN > USER, VISITOR meaning USER and VISITOR are "on the same level".)
Now if I want to call
roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()));
I need a RoleHierarchy Implementation object. spring-security provides one but the setter accepts only this weird string representation. I don't really want to transform my database results into a string representation but rather work with some kind of tree structure.
So the only way seems to be extending the Implementation and writing my own setter to work with my database result set to build the rolesReachableInOneStepMap and rolesReachableInOneOrMoreStepMap.
Or does anyone know of a different solution?
Thanks for any pointers or confirmation!

We came up with our own solution by implementing RoleHierarchy, resolving the hierarchy inside the UserDetailsService and using a m:n self referencing relationship between Role and Role.
The hierarchy is thus saved in the database, cached at application launch, updated when needed and used to resolve all GrantedAuthorities when creating a UserDetails object on login.

Related

RBAC nested permissions

I'm trying to implement the RBAC (Role-Based Access Control) on a website.
The problem is the permission of nested objects.
Suppose we have some projects on the website. Each user can have a role in each project. e.g. user1 has the admin role in project1 and the customer role in project2.
Admin role, for example, consists of some permissions like Adding subproject, Deleting subproject, etc.
All docs I've read about RBAC, define general permissions like Add subproject, but when a user has this permission, it can add subproject for all projects not a specific project (here project1).
How can I restrict such permission to a specific project?
One bad solution is to define new permissions for each project. So the permissions will be Add subproject to project1, Delete subproject from project1, etc. and defining the corresponding roles like project1 Admin.
But I don't feel good about this redundancy; while the projects themselves can be added/removed, dynamically.
I think you've run into one of the known limitations of RBAC: permissions can only be assigned to user roles (not to resources or operations).
Recently, there has been growing development in permissions services based on Google's Zanzibar paper which describes a more general permissions system that supports describing resources, users, and relationships between them.
In a Zanzibar based system, you would define a resource for Projects, an admin and customer relation for Projects, and then defines tuples to manifest actual relationships representing your data. Thus, you can define <project1, admin, user1> and <project2, customer, user1>, a straightforward way to represent and check granular permissions on resources. This is a conceptual overview but there are concrete services where you can read their implementation specific details as well as try them out.
I stumbled across your post while researching authorization as part of my new job so I'm adding this answer in case others encounter similar challenges. Some resources we've put together than may be useful:
What is Zanzibar?: blog post that gives an overview
Playground: an interactive tool for writing and testing namespaces (there's a pre-written RBAC example you can test as well)
Disclaimer: I am a RBAC beginner
The way i understood RBAC is that you have Permissions which combine actual Resources and Operations.
In your case: The Resource would be "project1" and the Operation would be "create_subproject", so the Permission would be called "project1.create_subproject", which indicates that you have one permission per Resource, hence the mentioned redundancy.
My proposal to your question is to introduce a ResourceGroup. This is not part of the NIST RBAC Standard though. A ResourceGroup would combine Resources of a common type.
The access check goes through all objects in the ResourceGroup and if it finds your specific Resource it can evaluate the allowed Operations
OK. I've got a solution workaround for such a situation.
My problem with granularity was raised because of an extra-large context: where projects themselves are considered to be resources having independent permissions. But the problem is that with such permissions, other nested permissions are not independent anymore. (i.e. create_subproject permission is depended on project_access permission; which breaks granularity.
So the workaround is to define permissions at the project level (assuming the project itself is accessible), and define the tuples of <user, role, project> to specify which user has which roles on each project.

Queries in DFC and WDK in documentum

I have below queries in DFC and WDK:-
1) TBO is type base objects and is for specific object type in documentum. SBO is for global use. Can we make a SBO code to act like a TBO, if yes then how? How can I make my SBO specific for a particular object type.
2) How can I call a behavior class from an action.xml in WDK? If I dont want to use the component in my WDK customization. Any examples to support these queries will be appreciable.
3) Why is scope required in WDK? What is its role and can scope override over privileges in terms of hierarchy. If a user is provided a scope for a component in WDK but he/she doesnt have sufficient privileges to access it in documentum. Can the user still access the particular component?
4) Can folder security values override basic object level permissions? Which will come first folder security or basic level permissions or privileges?
Thanks!!
Deb
This is not kind of question for SO, at least in most parts. However:
1.) TBO and SBO are just architectural approaches for specific requirements. If you have specific code that you want to run for objects of specific type and not only for objects of subtypes, than you need to change object model to apply logic for all objects in type hierarchy. This isn't a problem with Documentum object/type model.
For example: You have custom_document as subtype of dm_document and custom_child1_document and custom_child2_document, both subtypes of custom_document. You have TBO set to custom_child2_document.
You don't want to apply SBO to have custom logic available everything under dm_document.
Just add TBO to type custom_documentm and you'll have your logic for all types under dm_document.
2.) You cannot call behavior class without invoking component. If you have specific code you want run from other places, isolate it at some other place and run it at will.
3.) You don't need to specify scope for your WDK configuration. However, once you learn WDK in details you will find it useful.
4.) Folder is object. You need to know that when you access objects via folders you need access permission for both folder and document linked to that folder (Read level is enough). You need only permissions on object id you access that object from DQL for instance. Basic and extended permissions are meant to be used in specific cases, you don't need extended permissions to read object content if you have Read basic permission on your object. However you need Relate basic permission + Run procedure extended permsission on target Workflow to start workflow with that specific object as attachment/package. Different rules go when you want to add object inside specific folder. But this is long story.
Regarding folder security - check this article.

Implementing Access Control in a system

I came across many different models for the Access Control in a system. When implementing an Access Control model in any system, we usually hard code the rules/rights in the database(considering an RDBMS) by creating separate tables for the Access Control. Also, these rules/rights can be stored in an XML database.
I would like to know what is the difference between storing the rules on RDBMS and on an XML database? Also, when should we use XACML for implementing an Access Control model in a system? I mean, how one can decide whether one should hardcode the rules/rights in the database or one should use XACML policy language?
Thanks.
Disclaimer: I work for Axiomatics, a vendor implementation of XACML
Storing authorization logic if you go your own way could be done either in the RDBMS or in an XML database. It doesn't matter. I doubt that XML brings you any added capabilities.
Now, if you want an authorization system that can cater for RDBMS systems and other types of applications too (CRM, .NET, Java...) then you want to use a solution that is agnostic of the type of application it protects. That's the goal of XACML, the eXtensible Access Control Markup Language.
XACML provides attribute-based, policy-based access control (ABAC and PBAC). This gives you the ability to write extremely expressive authorization policies and managed them centrally in a single repository. A central authorization engine (called Policy Decision Point or PDP) will then serve decisions to your different applications.
As Bell points out, the minimum set of attributes you will need is typically attributes about the user (Subject), the resource, and the action. XACML also lets you add environment attributes. This means you can write the following type of policy:
Doctors can view the medical records of patients they are assigned to.
Doctors describes the user / subject
view describes the action
medical records describes the targeted resource
of patients describes the targeted resource too. It's metadata about the resource
they are assigned to is an interesting case. It's an attribute that defines the relationship between the doctor and the patient. In ABAC, this gets implemented as doctor.id==patient.assignedDoctorId. This is one of the key benefits of using XACML.
Benefits of XACML include:
- the ability to externalize the authorization logic as mentioned by Bell
- the ability to update authorization logic without going through a development/deployment lifecycle
- the ability to have fine-grained authorization implemented the same way for many different applications
- the ability to have visibility and audits on the authorization logic
HTH
The two are not mutually exclusive.
An XACML policy describes how to translate a set of attributes about an attempted action into a permitted/denied decision. At minimum the attributes would be who the user is (Subject), what they are trying to do (Action) and what they are trying to do it to (Object). Information such as time, the source of the request and many others can be added.
The attributes of the user and the object will still have to be stored in the database. If you are grouping users or objects to simplify administration or to simplify defining access control rules then you're going to have to manage all of that in the database to. All that data will then need to be passed to the XACML Policy Decision Point to return the permit/deny decision.
The advantage of using XACML to define these rules, rather than writing your own decision logic for the rules defined in the database, is that the assessment of the rules can be handed off to an external application. Using a mature, tested XACML implementation (there are open source options) will avoid you making any mistakes in building the checks into your own code.
Hardcoding the policies in your code is a very bad practice I think. In that case you mix the business logic of your resources and the permission check of the access control system. XACML is a big step in the right direction because you can create a fully automatic access control system if you store your rules in a separated place (not hardcoded in the business logic).
Btw you can store that rules in the database too. For example (fictive programming language):
hardcoded RBAC:
#xml
role 1 editor
#/articles
ArticleController
#GET /
readAll () {
if (session.notLoggedIn())
throw 403;
if (session.hasRole("editor"))
return articleModel.readAll();
else
return articleModel.readAllByUserId(session.getUserId());
}
not hardcoded ABAC:
#db
role 1 editor
policy 1 read every article
constraints
endpoint GET /articles
permissions
resource
projections full, owner
role 2 regular user
policy 2 read own articles
constraints
endpoint GET /articles
logged in
permissions
resource
projections owner
#/articles
ArticleController
#GET /
readAll () {
if (session.hasProjection(full))
return articleModel.readAll();
else if (session.hasProjection(owner))
return articleModel.readAllByUserId(session.getUserId());
}
As you see the non hardcoded code is much more clear than the hardcoded because of the code separation.
The XACML is a standard (which knows 10 times more than the example above) so you don't have to learn a new access control system by every project, and you don't have to implement XACML in every language, because others have already done it if you are lucky...

Is it possible to allocate one user (entry) below two different OU (Organizational Unit) in OpenLDAP?

I'm planning the structure of a brand new OpenLDAP server to integrate it with Moodle.
I thought about the following structure:
O=CompanyName
OU=ProjectName
uid=UserID001
uid=UserID002
uid=UserID003
OU=ProjectName
uid=UserID002
See that the same user 'uid=UserID002' can be allocated in one or more Projects. This would make synchronization between softwares and LDAP easier.
Is it possible to do that using OpenLDAP? I heard that IBM LDAP allow it, is it true? Is there any kind of 'symbolic link' to an entry?
You can do that using LDAP aliases easily enough, but the general idea in these cases is to use a schema such as organizationalRole for the project nodes. organizationalRole has multi-valued roleOccupant attribute, which are DNs of entries that occupy the role ... rather than creating an entire forest of subcontexts under each project. So you just search each project, or all of them, for (roleOccupant={0}) where {0} is supplied as the DN you're checking on.
Some directory servers support the notion of attribute uniqueness, going so far as to have a plugin for uid uniqueness. You should contact your directory server administrator to determine whether your local directory services support the notion of attribute uniqueness, and if it does, is the attribute uniqueness configured for the uid attribute.
As far as the general concept of naming attribute uniqueness is concerned, there is nothing about your idea that should not be supported by a professional-quality directory server that supports the group of LDAP standards. uid is just an attribute, and in your example there is nothing special about it except that it becomes a relative distinguished name component. The object that identifies an entry in the directory server is the distinguished name, the uid is an attribute like any other.
According to RFC4512, LDAP does support the notion of aliases, but that functionality should not be used in your case.
You're best to use the memberOf overlay.
You use the groupOfNames object class (that's already there) to specify members that will belong to project entry using the member attribute. You can add as many member attributes as you want, where each member attribute is a (full) DN.
Personally I would create my own objectClass (e.g. called project) that extended the groupOfNames class so I could add extra project related attributes to it. But depends how complex you want to get.
You would then redefine your structure like the following...
O=CompanyName
OU=People
uid=UserID001
uid=UserID002
uid=UserID003
OU=Projects
cn=ProjectName
cn=ProjectName...
This would make your structure a lot cleaner and with the Project items (eg. cn=ProjectName) being kept separate from your user entries. The project items would be your groupOfNames classes that contain member attributes to the people in the OU=People class (e.g. member: uid=UserID001,OU=People,O=CompanyName).
What the memberOf overlay will do, when installed into your olap, will add an additional attribute called member of to your ldap search results (it's dynamically generated).
This is quite a common overlay that's used, and is even used by AD servers, so this method is commonly used and you might find that Moodle will understand them.
A little thing to watch out for when testing your setup.... ldapsearch queries won't show the memberof attribute by default, so you will need to specifically ask for it. e.g.;
ldapsearch -Y EXTERNAL -H ldapi:/// "(objectClass=groupOfNames)" uid, memberof
That one stumped me when I first started using them. I think there is an 'all' option that will force the search to show the hidden attributes, but can't think what it is at the moment. Check out ldapsearch's man pages.
Anyway, hope that helps.. :)

When should an object be included as a member of another object, and when should it always standalone?

An example problem:
On Stack Overflow, a question page shows a number of different answers. In displaying these answers, the site also gives information about the author of the answer. This means that although the number of badges a given user has has nothing to do with an answer in and of itself, that data still needs to be retrieved in order to display the page.
From what I can see, there are three different ways to go about pulling this view data in a model:
A Post object could include a full User object as a member. The view would then access the user like this: $post->user->getReputation(). This seems cleaner, since a Controller could just request the posts and be done with it, but yet inefficient since a Post probably doesn't always need a full-blown User. I suppose it works well enough if the User object is relatively light, which it probably would be. The problem would then be that you would need to duplicate User retrieval code as part of the Post retrieval query.
The Post object could hold just an ID for a User. When the Post, or Posts, are returned to the Controller, the Controller could then extract the unique User IDs from the returned set and pass them to a User factory. The returned User objects would then be passed along with the original Posts set to the View as a separate collection. The view could then grab user info using something like $users[$post->getUserId()]->getReputation().
A hybrid approach: Include the User object inside the Post object, but have the unique id extraction and User retrieval as part of the Post retrieval method. i.e. Post::getPosts() would grab all relevant posts and convert them to objects with null User members, then it'd extract all user ids and pass them to User::getUsers(), then assign the Users to the relevant Posts before returning the set of Posts to the caller.
I guess what I'm getting at is, how do I know when an object needs to contain another object fundamentally? Is it unclean/a code smell to instead have such related objects returned separately, with neither object knowing the other has been retrieved. I'm leaning towards the separate retrieval concept - it seems the most efficient - but it really does feel like they're too related for that to make sense.
There is also a solution in between 1 and 2. You can have a lazy loading proxy for the user class. With this solution you can have best of both worlds because the proxy is interchangeable with the real thing so depending on the situation you can have the object itself or the proxy.
Edit:
I'll try to explain this with an example.
Say that you have a view where you don't need user info, then you can instruct/configure your post factory to use the lazy proxy (see wikipedia)for the user which will only contain an ID. So no access to users is needed.
In another view you occasionally need to access user info but only for some posts, here again you instruct/configure your factory to include the lazy proxy for the user.
But when you actually need access to the user info, you can access the proxy object that will then load the actual user object and redirect messages to it.
In yet another view you need both post and user info, so here you instruct your post factory to use actual user objects.
It seems to me that this is another case of dependency injection. A general enough idea that could help you.
DEPENDENCY INJECTION WIKI
Read something about the Inversion Of Control also.
why not add optional member to model to know informations?? you can ignore when you don't need and can use when you do need.