我在 openldap 服务器中有一个用户目录,位于基本 DN 下ou=users,dc=mydomain
。用户条目如下uid=user1,ou=users,dc=mydomain
我当前的 ACL 是:
{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none {4}to dn.subtree="ou=users,dc=mydomain" by self read {3}to dn.exact="dc=mydomain" attrs=entry by users search by * none {2}to dn.base="" by * read {1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none
这些允许用户查询并找到自己的条目。但如果经过身份验证的用户用户1搜索设置了过滤器的基本 DN (uid=user1)
,未找到任何条目。换句话说:ldapsearch -H ldap://myserver -b "ou=users,dc=mydomain" -D "uid=user1,ou=users,dc=mydomain" -x -W
不返回任何内容,而ldapsearch -H ldap://myserver -b "uid=user1,ou=users,dc=mydomain" -D "uid=user1,ou=users,dc=mydomain" -x -W
返回 的条目user1
。
我需要如何调整 ACL 以便用户可以通过对基本 DN 进行过滤搜索找到他自己的条目(且只能找到他自己的条目)?
答案1
定义 OpenLDAP ACL 很棘手。
大多数情况下,ACL 问题是由 ACL 本身及其 who 子句(by ...)的处理顺序引起的,并且 ACL 隐式地以by * none
停止控制流而结束。
您正在使用动态配置cn=配置这使用 已排序架构中的扩展以保留某些属性值的顺序,例如访问控制。
因此,处理 ACL 的顺序是:
{0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none
{1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read
{2}to dn.base="" by * read
{3}to dn.exact="dc=mydomain" attrs=entry by users search by * none
{4}to dn.subtree="ou=users,dc=mydomain" by self read
{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none
让我们详细看看您的 ACL:
{0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none
这可能是从某些默认配置中获取的规则。从它开始是可以的,但我建议进行一些重构:
- 省略属性影子最后更改因为 LDAP 影子是一个不完善的概念。如果您确实使用影子映射,此 ACL 将允许用户规避影子密码过期。
- 改变 who-clauses 的顺序。一般来说,遵循首先提及“更高”特权的规则。
- 如果 cn=admin,dc=mydomain 已经是根域名这个数据库不需要那个 who 子句。
- 最好向组授予密码管理员权限。
- 不要通过包容性
write
访问授予任何读取权限,而是使用只写权限=w
。
更好的使用:
{0}to attrs=userPassword by group="cn=admins,ou=groups,dc=mydomain" =w by self =w by anonymous auth by * none
{1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read
如果dc=mydomain
是数据库后缀,那么根据你的问题,这个 ACL 对我来说没有多大意义。也许是一些测试遗留下来的?
{2}to dn.base="" by * read
如果将其放在数据库配置条目中,则无效。必须将其添加到前端配置条目中cn=配置(以前是静态配置 slapd配置文件在任何之前数据库部分)。
{3}to dn.exact="dc=mydomain" attrs=entry by users search by * none
我会在 ACL 列表的末尾放置一个这样的 ACL,这样它就不会阻止访问入口此时。如果你想使用任意搜索基础,例如ou=用户,dc=我的域您必须将此搜索权授予整个子树。
因此将其放在 ACL 的末尾并删除 {3} 或...
{6}to dn.subtree="dc=mydomain" attrs=entry by users search by * none
...移动此规则:
{4}to dn.subtree="ou=users,dc=mydomain" by self read
可能应为最后一个 ACL 并替换 {3}。请参阅 {5} 的注释。
{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none
这里的问题:
by self write
由于{4} 中的 ,将永远无法到达by self read
。- 由于
by * none
{4} 中隐含的内容,因此根本无法达到此 ACL。 - 再次:授予访问权限根域名没有必要
- 再次:最好授予组管理员访问权限
- 使用更好的 who-clause 顺序
- 重新考虑是否真的想授予用户自己对所有属性的写权限
更好的:
{5}to * by group="cn=admins,ou=groups,dc=mydomain" write by self write by * none
最重要的调试选项之一是启动拍打记录其 ACL 处理:
/usr/sbin/slapd … -d config,stats,stats2,acl
因此,这些提示应该可以帮助您开始着手处理 ACL,自己解决问题。一定要三思而后行。在我看来,您的规则中有一些相互矛盾的假设。
但显然没有办法深入研究文档:
如果您想详细了解 ACL,您应该查阅各种在线文档:
答案2
这回答给我决定性的线索。我唯一需要改变的是建议的搜索从顶部 dn (dc=mydomain) 到用户 dn (ou=users,dc=mydomain) 的 acl
将 ACL 更改为以下方式即可达到目的:
{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none {4}to dn.subtree="ou=users,dc=mydomain" by self read {3}to dn.exact="ou=users,dc=mydomain" attrs=entry by users search by * none {2}to dn.base="" by * read {1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none