使用Python检查LDAP访问权限
我正在为一个LDAP服务器写一个网页前端(使用django)。这个系统里有不同类型的人,他们的权限也不一样,所以我设置了LDAP的访问控制列表(ACL),来管理谁可以查看或编辑特定的属性。
现在,判断一个用户是否有读取权限很简单——试着去读取一下,看看能不能拿到数据就知道了。
但我找不到一个优雅的方法来在实际尝试写入之前,区分用户是否有写入权限。也就是说,我想在界面上清楚地显示,当前登录的用户是可以编辑的,还是只能读取。这样用户就不会去尝试编辑那些他们没有权限的属性。
我想到的唯一办法就是暂时往某个属性里写入一个虚假的值,然后看看是否成功。如果成功了,我就把原来的值恢复回来,这样我就知道这个用户有写入权限了。然后我就可以把这个属性显示为可编辑的。
但这样做的问题是,如果在写入虚假值后,服务器崩溃了,而原来的值还没恢复,那我的LDAP服务器里就会留下虚假的值。
我需要的是一种方法,可以查询这些访问控制列表,类似于我查询模式定义的方式。但也许LDAP不允许这样做?
有什么想法吗?
艾萨克
3 个回答
在OpenLDAP中,访问控制列表(ACL)的定义是在数据树之外的。如果你想通过ldap查询来访问ACL,可以使用FedoraDS(389目录服务器):http://directory.fedoraproject.org/wiki/Howto:AccessControl
你也可以看看OpenDS(https://www.opends.org)
我想我会尝试“测试”的方法,如果速度太慢的话,也许可以加点缓存。之所以想把访问控制列表(ACL)的定义只放在ldap服务器上,是因为还有其他方式可以和服务器互动(会有命令行工具,还有标准的ldap工具),所以我希望所有这些接口在访问控制方面能够保持一致,只在一个地方定义ACL。
在openldap中,访问控制列表(ACL)是通过组织单位(OU)和/或区分名称(DN)来管理的,可以用正则表达式来检查。
举个例子:
access to attrs=userPassword
by anonymous auth
by self write
by dn.base="ou=users_with_userPassword_write_access,dc=myproduct,dc=org" write
by dn.exact="cn=manager,dc=myproduct,dc=org" write
by * none
access to *
by dn.exact="cn=manager,dc=myproduct,dc=org" write
by dn.base="ou=users_with_powerfull_write_access,dc=myproduct,dc=org" write
by * none
关于登录用户的DN(可以用whoami_s
和python-ldap获取),你可以判断这个用户是否有某些权限。你不需要测试是否可以写入数据,只需要在你的django应用中实现一个函数来检查DN。
也许你在说ACL是动态生成的?
关于你的评论,如果你的ACL是静态的,了解ACL的最简单方法就是实现一个Python工具来管理这些ACL。就像我之前的例子:
W_ACCESS_OU = "ou=users_with_powerfull_write_access,dc=myproduct,dc=org"
def check_write_access(user_dn):
return is_dn_base(W_ACCESS_OU, user_dn)
目前,python-ldap无法获取slapd.conf中的ACL... 而且解析slapd.conf并不安全(因为slapd.conf可能在系统的“任何地方”,而且ACL的声明可能很复杂),另外,尝试在LDAP后端写入数据也会消耗很多时间。
我知道这并不是很令人满意。另一种解决方案是使用一个“服务用户”。只有这个用户可以在LDAP后端进行写入。
这简化了ACL的写入:
access to *
by dn.exact="cn=manager,dc=myproduct,dc=org" write
by * none
然后,对于普通用户,你设置一个授权标志。当你的登录用户想要执行某个操作时,你的应用会检查这个标志。如果这个标志是OK的,服务用户就会在后端写入数据。
这是我们在一个应用中采用的策略。
在这两种情况下,ACL的检查都是由我们的应用来完成,而不是由LDAP后端来完成。