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

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.. :)

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.

How do you add a user to a group using Apache Directory Studio

I am using Apache Directory Studio to set up an initial user on an LDAP partition. I have added the user, and I have a group (Administrators) that I am trying to add that user to.
Users are ou=users and groups are ou=groups and where copied from ou=system. The user was created by adding an inetOrgPerson class entry.
How do I add a user to a group? What kind of class would I use and what attributes are required?
I feel I am missing a lot of information with LDAP. I got this far by ghacking (googling and hacking - the least efficient thing you can do). So, where do I go that will tell me what to do and how to get it done in a cook-book style guide, or at least some sort of detailed reference on the classes and schemas that would define what each is used for
Any help is highly appreciated!
Select your group
Right Click on the right side and select "new attribute"
Type member and/or select from list
Hit the browse button and search for your user or enter the path
Hit OK button
Using Apache Directory Studio you can interactively add a user to e.g. a groupOfNames entry by adding a value (Ctrl++) to the multivalued attribute member. Studio comes with a DN value editor which allows you to browse the Directory Information Tree for the user to add.
As for the objectClass to use for groups and users, you should consult the relevant RFC's (e.g. 4519). For a more prosaic lecture there are a couple of good books (e.g. Howe: Understanding and Deploying LDAP Directory Services).

difference between cn and ou in ldap

My Directory experience until now was originally Novell's NDS and eDirectory, and more recently, MS Active Directory, but now I'm now having to work directly with ldap (OpenLdap 2.4 on Zimbra.)
I'm more than a little confused with the naming in ldap, and I really haven't been able to find what I'm looking for in numerous google searches:
In eDir and AD, when an object was labeled with the cn= it was a leaf object, while an object labeled with ou= was a container object. But that doesn't seem to be the case in ldap.
For instace, let's say I want to list the installed schemas in my dit, I can use the command:
ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn
The results returned are:
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
Is there documentation explaining why the objects schema and config, which are clearly container objects, are still labeled as cn? Or can someone please just explain to me when to use the cn label on container objects, rather than the ou label?
Maybe this is documented in a book I just ordered from Amazon, "The ABCs of LDAP" by R. Voglmaier from Amazon. It should be arriving sometime next week.
Leaf and non-leaf have nothing to do with it.
CN stands for Common Name and is an attribute of several person-related classes such as inetOrgPerson. But there's nothing stopping it being an attribute of other classes, such as organizationalRole.
OU stands for Organizational Unit and is an attribute of the organizationalUnit class.
In both cases the attribute forms part of the DN of an object of those classes.
You would normally expect an object with OU to be a non-leaf, and a person to be a leaf, but there is nothing inherent about it.
i can understand your confusion bit you took the most complicated thing to try to understand it, as the config-branch of OpenLDAP is a special thing.
One thing to keep in mind us that the objectclass of an entry (and I always try to avoid calling them "leaves" or "containers") defines whether an OU or CN should or can be an attribute of it. Depending on the set objectclasses it might be possible (not necessarily usefull) to have both attributes in an entry.
So if you beed to know whether to use CN or OU, have a look at the objectclass.
By convention the OU is used to describe an OrganizationalUnit like a department inside a larger organization whereas the CommonName can be used for vitually anything. And as you are looking and trying to understand the LDAP information in the config-part of the LDAP there is not really any Organizational unit available. therefore there are no OUs defined.
I'm trying to avoid those "leaf" and "container" naming as it implies that a container is just a collection of things without informstions attached which in LDAP might not be the case. A "Container" might have more attributes available than the entries "stored inside".
There is also a great book from O'Reilly about LDAP-Administration which might be interesting.
Hope that helps somewhat.

Api URI Design Preference

A quick api uri design question. We have resources that belong to our clients. These resources can be edited / viewed / deleted by the client who entered them into our system. The resources can be searched by all clients but access is only granted if certain criteria is met (client has level 3 access etc).
Choice 1: include the client who owns the resource in the uri.
client/:clientname/widgets
client/:clientname/widgets/:id
Choice 2: ditch the whole "client/:clientname" since this part of the uri has to be verified and checked against the credentials of the user accessing the information.
/widgets
/widgets:id
We have other resources other than widgets that also belong to clients.
Which way is the more preferred way and why? Cheers.
The only advantage that Choice 1 gives it that it allows you to effectively namespace widgets/whatever by the user that uploaded them. Similar to Github, how different users can have projects with the same name. If Github were to exclude the username, no two users could have a project with the same name. If the widgets are all unique, I would go with option two and you will have a 1:1 mapping from a widget the the user that created it, thus supplying it is just extra work for whoever is calling it.
If you can have the same widget name for different users, use an approach which includes the username. You may not need to actually use the 'client' word in your url though; using a path like '/:clientname/widget/:widgetid' instead.
Note that this is kind of an opinion based question, so you may get different answers. You'll have to weigh the information provided and in the end make your own decision.

Dynamic Role Hierarchy in Spring Security

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.