Hello everyone,
I am in the process of implementing a role concept via ACLs and hope for a hint so that I don't invent the wheel a second time.
Specifically, it is about identity management for schools. A user (object) can have several roles in multiple schools. Permissions on other LDAP objects can thus differ depending on the role(s) the user and the object have in the same school(s).
For example, a user could have been assigned the following roles that are scattered over several schools: → "Teacher" in school 1 → "School admin" in school 2 → "Parent" in school 3 → both "Teacher" and "Staff" in school 4
ACLs should now be defined accordingly, e.g. → the role "teacher" at school X can reset the password for the role "student" at school X → the role "teacher" at school X *cannot* reset the password for the role "student" of school Y → the role "school administrator" at school X can reset the password for the roles "student" and "teacher" at school X → ...
So far I have not seen any way to map such a construct via groups or sets without including a separate ACL for each group, which is a performance issue. Is there another way to map the role concept besides implementing an own dynacl module?
Greetings, Daniel
Daniel Tröder wrote:
Hello everyone,
I am in the process of implementing a role concept via ACLs and hope for a hint so that I don't invent the wheel a second time.
Specifically, it is about identity management for schools. A user (object) can have several roles in multiple schools. Permissions on other LDAP objects can thus differ depending on the role(s) the user and the object have in the same school(s).
For example, a user could have been assigned the following roles that are scattered over several schools: → "Teacher" in school 1 → "School admin" in school 2 → "Parent" in school 3 → both "Teacher" and "Staff" in school 4
ACLs should now be defined accordingly, e.g. → the role "teacher" at school X can reset the password for the role "student" at school X → the role "teacher" at school X *cannot* reset the password for the role "student" of school Y → the role "school administrator" at school X can reset the password for the roles "student" and "teacher" at school X → ...
So far I have not seen any way to map such a construct via groups or sets without including a separate ACL for each group, which is a performance issue. Is there another way to map the role concept besides implementing an own dynacl module?
I think a dynacl module is your only choice. Most people miss the difference between roles and groups - group membership applies all the time. Once you're a member of a group, the privileges of that group are omnipresent.
Whereas, membership in a role grants you these privileges *only for as long as you assert that role* and adopting a role is a temporary, bounded activity.
So you need, at the least, in an LDAP context, an exop that says "assume role X" and the corresponding "drop role X". Without these two primitives, you don't actually have roles or role-based access control. LDAP's spec for proxy authorization might be sufficient for this purpose.
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
I am in the process of implementing a role concept via ACLs and hope for a hint so that I don't invent the wheel a second time.
I applaud your decision to not reinvent the wheel but have doubts about using ACL’s to accomplish (more later)
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
Specifically, it is about identity management for schools. A user (object) can have several roles in multiple schools. Permissions on other LDAP objects can thus differ depending on the role(s) the user and the object have in the same school(s).
Classic RBAC scenario for sure. Nice job using a standards-based approach btw.
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
For example, a user could have been assigned the following roles that are scattered over several schools: → "Teacher" in school 1 → "School admin" in school 2 → "Parent" in school 3 → both "Teacher" and "Staff" in school 4
ACLs should now be defined accordingly, e.g. → the role "teacher" at school X can reset the password for the role "student" at school X → the role "teacher" at school X *cannot* reset the password for the role "student" of school Y → the role "school administrator" at school X can reset the password for the roles "student" and "teacher" at school X → ...
Why use ACL’s for fine-grained authZ?
It’s drawbacks, - Not standard / LDAPv3 server lock-in (might not be a problem for you) - difficult to maintain and test (complex)
To determine if necessary another question - how are your applications interacting with the directory. Are they connecting using LDAPv3 operations (like search and bind), or is there are higher level abstraction in place, (like mod_authnz_ldap)?
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
So far I have not seen any way to map such a construct via groups or sets without including a separate ACL for each group, which is a performance issue. Is there another way to map the role concept besides implementing an own dynacl module?
There are many ways to achieve RBAC using LDAP. Typically these other methods will use a library that gets imbedded into your application to use for the security checks. That way the directory ACL’s remain simple, and the bits corresponding to the policy live inside of objects that are stored within it, not in metadata for its config.
Disclaimer, I’m a PMC here: http://directory.apache.org/fortress/
— Shawn
Shawn McKinney wrote:
Why use ACL’s for fine-grained authZ?
It’s drawbacks,
- Not standard / LDAPv3 server lock-in (might not be a problem for you)
- difficult to maintain and test (complex)
You have both of these issues for every non-trivial access control system. Especially you need automated tests.
To determine if necessary another question - how are your applications interacting with the directory. Are they connecting using LDAPv3 operations (like search and bind), or is there are higher level abstraction in place, (like mod_authnz_ldap)?
That's the real question: Does the end-user ever impersonate directly on the LDAP connection (optionally via a web application).
Ciao, Michael.
TL;DR: When modeling roles one should start from the use-cases.
Howard Chu wrote:
Most people miss the difference between roles and groups - group membership applies all the time. Once you're a member of a group, the privileges of that group are omnipresent.
Whereas, membership in a role grants you these privileges *only for as long as you assert that role* and adopting a role is a temporary, bounded activity.
Hmm, probably we mean the same. But I'd like to re-phrase a bit:
Each use-case (the actual work to be done) defines which actor roles are allowed to exercise the use-case. The role can be determined in the simplest case just by simple group membership (e.g. super-power admin role) or by an arbitrary set of (dynamic) conditions.
In Æ-DIR the roles are mainly driven by use-cases and are always limited to a certain "scope", e.g. by relationship of objects to the zone(s) or by service group(s). [1]
For the use-cases affecting LDAP access (data maintenance, data retrieval) set-based ACLs are in effect which are indeed very slow. So a dynacl module would be nice for that. Or a custom LDAP server...
So you need, at the least, in an LDAP context, an exop that says "assume role X" and the corresponding "drop role X". Without these two primitives, you don't actually have roles or role-based access control. LDAP's spec for proxy authorization might be sufficient for this purpose.
I'd argue that for security reasons the change-role / change-hat action should never be possible without a (re-)authentication. So in Æ-DIR true role separation simply requires a separate user/system account. But that's me.
Ciao, Michael.
Michael Ströder wrote:
For the use-cases affecting LDAP access (data maintenance, data retrieval) set-based ACLs are in effect which are indeed very slow.
Ah, forgot to make that more clear (and people tend to miss that point):
Æ-DIR's ACLs are _static_ and work their way through the actual data which is changed to alter the effective access rights.
Ciao, Michael.
Hello,
On 04/22/2018 05:57 AM, Howard Chu wrote:
Daniel Tröder wrote:
Hello everyone,
I am in the process of implementing a role concept via ACLs and hope for a hint so that I don't invent the wheel a second time.
Specifically, it is about identity management for schools. A user (object) can have several roles in multiple schools. Permissions on other LDAP objects can thus differ depending on the role(s) the user and the object have in the same school(s).
For example, a user could have been assigned the following roles that are scattered over several schools: → "Teacher" in school 1 → "School admin" in school 2 → "Parent" in school 3 → both "Teacher" and "Staff" in school 4
ACLs should now be defined accordingly, e.g. → the role "teacher" at school X can reset the password for the role "student" at school X → the role "teacher" at school X *cannot* reset the password for the role "student" of school Y → the role "school administrator" at school X can reset the password for the roles "student" and "teacher" at school X → ...
So far I have not seen any way to map such a construct via groups or sets without including a separate ACL for each group, which is a performance issue. Is there another way to map the role concept besides implementing an own dynacl module?
I think a dynacl module is your only choice. Most people miss the difference between roles and groups - group membership applies all the time. Once you're a member of a group, the privileges of that group are omnipresent.
OK - good to know we might be on the right track.
Whereas, membership in a role grants you these privileges *only for as long as you assert that role* and adopting a role is a temporary, bounded activity.
So you need, at the least, in an LDAP context, an exop that says "assume role X" and the corresponding "drop role X". Without these two primitives, you don't actually have roles or role-based access control. LDAP's spec for proxy authorization might be sufficient for this purpose.
I read the rfc4370. It's very cool - it'd allow us to implement real roles. But AFAICS it requires the clients to actively request its use though. As our IDMs LDAP is accessible to 3rd parties, I don't think that will work for us.
In the meantime my colleague has written a (proof of concept) dynacl module "rolecmp". The proposed solution works with two attributes: * school: list of schools a user "belongs to" e.g. ['schoolA', 'SchoolB'] * role: list of "role:school" pairs describing the role(s) an object has, when accessing other objects of the same school, e.g.: ['teacher:schoolA', 'student:SchoolB', 'teacher:schoolZ', 'administrator:schoolZ']
The dynacl module "rolecmp" allows ACLs like this:
attrs=krb5...,samba...,userPassword,pw... by dynacl/rolecmp/teacher,schooladmin=student write by dynacl/rolecmp/schooladmin=teacher write
The dynacl module does implicitly compare the school part (behind the colon) of the "role" attribute of both the accessing and the accessed object. The accessing objects roles are all of those on the left side of the equality sign. The accessed objects role is on the right side.
In the above ACL, access would be allowed for example: * by a user with ['teacher:X', 'student:Y'] to a user with ['student:X', 'administrator:Z'], because 'teacher:X' and 'student:X' match. * by a user with ['teacher:Z', 'schooladmin:Y'] to a user with ['student:X', 'teacher:Y'], because 'schooladmin:Y' and 'teacher:Y' match.
Access would be denied for example: * by ['teacher:X', 'student:Y'] to ['student:Y'] * by ['schooladmin:X'] to ['student:Y', 'teacher:Z']
While the connection does not change from user to role, the authorization process decides only by compare roles (at places)... this can still be called role based authorization, right?
We like his PoC a lot: * It is very easy to read (esp. compared with sets). * It is easy to extend: we/our customers will be able to create new roles without touching the dynacl module! * In tests it was at least not slower than our current set-based ACLs.
Can you think of a conceptual or technical problem with this solution?
Greetings Daniel
PS: as a bonus, this will allow 3rd parties to do queries like this: * Is user 'uid=foo' a student (anywhere)? --> '(&(uid=foo)(role=student:*))'. * Is user 'uid=bar' a teacher at school "X"? --> '(&(uid=bar)(role=teacher:X))'.
We'll also need a role:school definition like 'administrator:*' to express "is an administrator in all schools". Not sure about using the asterisk here though...
Hello,
On 04/24/2018 04:28 PM, Shawn McKinney wrote:
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
I am in the process of implementing a role concept via ACLs and hope for a hint so that I don't invent the wheel a second time.
I applaud your decision to not reinvent the wheel but have doubts about using ACL’s to accomplish (more later)
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
Specifically, it is about identity management for schools. A user (object) can have several roles in multiple schools. Permissions on other LDAP objects can thus differ depending on the role(s) the user and the object have in the same school(s).
Classic RBAC scenario for sure. Nice job using a standards-based approach btw.
Thanks. I wasn't completely... "complete" - about our project. So in the interest of disclosure: ;) The product is not new, but exists for some years now (https://www.univention.com/products/ucsschool/). It is completely open source and free as in beer (except support ofc). The LDAP tree is replicated from the master to >=1 LDAP slave per school. All of a schools LDAP objects are in a ou=.. subtree. For security reasons the replication to the LDAP servers in the school slaves is "selective": only global (above ou=..) objects and their own OU subtree is replicated to each slave. With the exception of user objects, which can "belong" to multiple schools (OUs) by having them listed in a "school" attribute (and their groups as well). The ACLs are written so that user objects and their references (groups) can also be replicated to those "additional" OUs. There are three hard coded roles (staff, student, teacher) and the ACLs are getting really hard to maintain (for example https://github.com/univention/ucs-school/blob/4.3/ucs-school-ldap-acls-maste...). As we want to be able to add more roles without having an ACL explosion and customers are asking for ways to query the LDAP for "role@school", we are now investigating new approaches to authorization.
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
For example, a user could have been assigned the following roles that are scattered over several schools: → "Teacher" in school 1 → "School admin" in school 2 → "Parent" in school 3 → both "Teacher" and "Staff" in school 4
ACLs should now be defined accordingly, e.g. → the role "teacher" at school X can reset the password for the role "student" at school X → the role "teacher" at school X *cannot* reset the password for the role "student" of school Y → the role "school administrator" at school X can reset the password for the roles "student" and "teacher" at school X → ...
Why use ACL’s for fine-grained authZ?
It’s drawbacks, - Not standard / LDAPv3 server lock-in (might not be a problem for you)
Our main product is a Linux distribution. UCS@school is kind of an addon. An LDAP server has been until now the right answer for the multitude of services that can be installed in a Linux distribution.
- difficult to maintain and test (complex)
Definitively.
To determine if necessary another question - how are your applications interacting with the directory. Are they connecting using LDAPv3 operations (like search and bind), or is there are higher level abstraction in place, (like mod_authnz_ldap)?
There's both: a Python based API that abstracts LDAP objects as Python objects, but there are a lot of services that query the LDAP directly - not to mention all the 3rd party software from ISVs.
On Apr 20, 2018, at 6:45 AM, Daniel Tröder troeder@univention.de wrote:
So far I have not seen any way to map such a construct via groups or sets without including a separate ACL for each group, which is a performance issue. Is there another way to map the role concept besides implementing an own dynacl module?
There are many ways to achieve RBAC using LDAP. Typically these other methods will use a library that gets imbedded into your application to use for the security checks. That way the directory ACL’s remain simple, and the bits corresponding to the policy live inside of objects that are stored within it, not in metadata for its config.
That'd be much simpler to maintain... and faster to extend. But as I wrote above, not an option.
On the positive side: I do like that authorization is as near to the data as possible. If the database makes both authentication and authorization, I won't have to worry about anyone coming between my code and the data, just because I forgot a firewall setting.
Greetings Daniel
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
Hi,
On 04/24/2018 05:04 PM, Michael Ströder wrote:
Shawn McKinney wrote:
Why use ACL’s for fine-grained authZ?
It’s drawbacks, - Not standard / LDAPv3 server lock-in (might not be a problem for you) - difficult to maintain and test (complex)
You have both of these issues for every non-trivial access control system. Especially you need automated tests.
To determine if necessary another question - how are your applications interacting with the directory. Are they connecting using LDAPv3 operations (like search and bind), or is there are higher level abstraction in place, (like mod_authnz_ldap)?
That's the real question: Does the end-user ever impersonate directly on the LDAP connection (optionally via a web application).
More and more services are moving towards SAML, OpenID etc., so one day we may be able to shield clients from the actual database. But for now a lot of our and 3rd party software access the LDAP directory directly.
Greetings Daniel
On Apr 24, 2018, at 10:28 AM, Michael Ströder michael@stroeder.com wrote:
Ah, forgot to make that more clear (and people tend to miss that point):
Æ-DIR's ACLs are _static_ and work their way through the actual data which is changed to alter the effective access rights.
+1 to static ACL’s to guard the directory and storing the access lists as data instead.
Daniel Tröder wrote:
The product is not new, but exists for some years now (https://www.univention.com/products/ucsschool/). It is completely open source and free as in beer (except support ofc). The LDAP tree is replicated from the master to >=1 LDAP slave per school. All of a schools LDAP objects are in a ou=.. subtree. For security reasons the replication to the LDAP servers in the school slaves is "selective": only global (above ou=..) objects and their own OU subtree is replicated to each slave. With the exception of user objects, which can "belong" to multiple schools (OUs) by having them listed in a "school" attribute (and their groups as well). The ACLs are written so that user objects and their references (groups) can also be replicated to those "additional" OUs.
Frankly I fail to understand how you securely handle cross-OU references and partial replication of OUs.
The other stuff pretty much sounds like what Æ-DIR is implementing with set-based ACLs (replace your "school/OU" by Æ-DIR's zone).
But as said: Sets are really slow. I'm curious to hear whether your dynacl module is faster than an equivalent set-based ACL approach.
Ciao, Michael.
On 04/25/2018 11:58 AM, Michael Ströder wrote:
Daniel Tröder wrote:
The product is not new, but exists for some years now (https://www.univention.com/products/ucsschool/). It is completely open source and free as in beer (except support ofc). The LDAP tree is replicated from the master to >=1 LDAP slave per school. All of a schools LDAP objects are in a ou=.. subtree. For security reasons the replication to the LDAP servers in the school slaves is "selective": only global (above ou=..) objects and their own OU subtree is replicated to each slave. With the exception of user objects, which can "belong" to multiple schools (OUs) by having them listed in a "school" attribute (and their groups as well). The ACLs are written so that user objects and their references (groups) can also be replicated to those "additional" OUs.
Frankly I fail to understand how you securely handle cross-OU references and partial replication of OUs.
Fun like this:
# Lehrer, Mitarbeiter und OU-Admins duerfen Schueler-Passwoerter aendern access to filter="objectClass=ucsschoolStudent" attrs=krb5KeyVersionNumber,krb5KDCFlags,krb5Key,krb5PasswordEnd,sambaAcctF lags,sambaPwdLastSet,sambaLMPassword,sambaNTPassword,shadowLastChange,shadowMax,userPassword,pwhistory,sambaPwdCanChange,s ambaPwdMustChange,sambaPasswordHistory,sambaBadPasswordCount by set="this/ucsschoolSchool & ([ldap:///]+user/entryDN+[?entryDN?base?%28%7C%28objectClass%3DucsschoolTeacher%29% 28objectClass%3DucsschoolAdministrator%29%28objectClass%3DucsschoolStaff%29%29])/ucsschoolSchool" write by * +0 break
root@m65:/etc/ldap# grep 'access to' slapd.conf | wc -l 100 root@m65:/etc/ldap# grep 'by set' slapd.conf | wc -l 35
UCS@school ACLs: https://github.com/univention/ucs-school/tree/4.3/ucs-school-ldap-acls-maste...
UCS ACLs: https://github.com/univention/univention-corporate-server/tree/4.3-0/managem...
The other stuff pretty much sounds like what Æ-DIR is implementing with set-based ACLs (replace your "school/OU" by Æ-DIR's zone).
Yes - I'm very intrigued by Æ-DIR!
But as said: Sets are really slow. I'm curious to hear whether your dynacl module is faster than an equivalent set-based ACL approach.
Yes... we have customers with >100.000 objects and when a query has to many constraints it can take several minutes to complete. We are now trying to get the dynacl module to replace as much set-ACLs as possible and comparing query speed. For now the motto is "not be slower" :) while gaining simplicity and extensibility. I'll keep you posted, and ofc it'll be open source :)
Greetings Daniel
On 4/25/18 6:31 PM, Daniel Tröder wrote:
We are now trying to get the dynacl module to replace as much set-ACLs as possible and comparing query speed. For now the motto is "not be slower" :) while gaining simplicity and extensibility. I'll keep you posted, and ofc it'll be open source :)
Any news on that? I'm very interested to learn whether a dynacl module gives better performance in your case.
Ciao, Michael.
On 10/11/18 12:12 AM, Michael Ströder wrote:
On 4/25/18 6:31 PM, Daniel Tröder wrote:
We are now trying to get the dynacl module to replace as much set-ACLs as possible and comparing query speed. For now the motto is "not be slower" :) while gaining simplicity and extensibility. I'll keep you posted, and ofc it'll be open source :)
Any news on that? I'm very interested to learn whether a dynacl module gives better performance in your case.
Ciao, Michael.
Hi Michael, unfortunately other things have gained priority other this. I don't see us getting anything going in (at least) the next 6 months :/
Sorry Daniel
openldap-technical@openldap.org