18.14. 高级访问控制:使用 Macro ACI
宏 ACI 提高了灵活性。例如,您可以添加子树并自动获得与其他子树相同的定制访问控制,而无需添加任何 ACI。作为副作用,ACI 数量会较小,但 Macro ACI 处理比常规 ACI 的成本要高得多。
宏是用于在 ACI 中代表 DN 或 DN 的部分占位符。您可以使用宏来代表 ACI 的目标部分或绑定规则部分的 DN,或两者。在实践中,当目录服务器获取传入的 LDAP 操作时,ACI 宏与 LDAP 操作的目标资源匹配。如果存在匹配项,则宏将被目标资源的 DN 值替代。然后目录服务器通常会评估 ACI。
18.14.1. 宏 ACI 示例
图 18.1 “Macro ACI 的目录树示例” 显示使用宏 ACI 来有效地减少 ACI 总数的目录树。此图图使用具有相同树结构的重复子域模式(ou=groups, ou=body)。此模式也在树中重复,因为 Example Corp. 目录树存储后缀 dc=hostedCompany2,dc=example,dc=com 和 dc=hostedCompany3,dc=com。
目录树中应用的 ACI 也具有重复模式。例如,以下 ACI 位于 dc=hostedCompany1,dc=example,dc=com 节点上:
aci: (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=hostedCompany1,dc=example,dc=com";)
此 ACI 将 DomainAdmins 组的读和搜索权限授予 dc=hostedCompany1,dc=example,dc=com 树中的任何条目。
图 18.1. Macro ACI 的目录树示例
以下 ACI 位于 dc=hostedCompany1,dc=example,dc=com 节点上:
aci: (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=hostedCompany1,dc=example,dc=com";)
以下 ACI 位于 dc=subdomain1,dc=hostedCompany1,dc=example,dc=com 节点上:
aci: (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=subdomain1,dc=hostedCompany1,dc=example,dc=com";)
以下 ACI 位于 dc=hostedCompany2,dc=example,dc=com 节点上:
aci: (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=hostedCompany2,dc=example,dc=com";)
以下 ACI 位于 dc=subdomain1,dc=hostedCompany2,dc=example,dc=com 节点上:
aci: (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=subdomain1,dc=hostedCompany2,dc=example,dc=com";)
在上面显示的四个 ACI 中,唯一不同的 DN 是 groupdn 关键字中指定的 DN。将宏用于 DN,可以在 dc=example,dc=com 节点上将这些 ACI 替换为树根的 ACI。这个 ACI 读取如下:
aci: (target="ldap:///ou=Groups,($dn),dc=example,dc=com") (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,[$dn],dc=example,dc=com";)
在新的 ACI 中使用 target 关键字(之前没有使用)。
在本例中,ACM 的数量从 4 个减少到一。真正优点是您在目录树中减少重复模式的数量。
18.14.2. 宏 ACI 语法
宏 ACI 包括以下类型的表达式来替换 DN 或 DN 的一部分:
- ($dn)
- [$DN]
- ($attr.attrName),其中 attrName 代表目标条目中包含的属性
在本节中,用来提供绑定凭证的 ACI 关键字(如 userdn、roledn、groupdn 和 userattr )被集中称为 主题,而不是 ACI 的目标。宏 ACI 可以在目标部分或 ACI 的主题部分使用。
表 18.5 “ACI Keywords 中的宏” 显示您可以使用 DN 宏的 ACI 的部分:
Macro | ACI Keyword |
---|---|
($dn) | target, targetfilter, userdn, roledn, groupdn, userattr |
[$DN] | targetfilter, userdn, roledn, groupdn, userattr |
($attr.attrName) | userDN, roledn, groupdn, userattr |
适用以下限制:
- 如果您在 targetfilter, userdn, roledn, groupdn, userattr 中使用 ($dn),则必须定义一个包括 ($dn) 的目标。
- 如果您在 targetfilter, userdn, roledn, groupdn, userattr 中使用 [$dn],则必须定义一个包括 ($dn) 的目标。
注意
在使用任何宏时,您始终 需要一个包含 ($dn) 宏的目标定义。
您可以组合 ($dn) 宏和 ($attr.attrName) 宏。
18.14.2.1. 宏匹配($dn)
($dn) 宏被 LDAP 请求中目标资源的匹配部分替代。例如,您在 cn=all,ou=groups,dc=subdomain1,dc=hostedCompany1,dc=example,dc=com 条目中有一个 LDAP 请求,其定义目标如下:
(target="ldap:///ou=Groups,($dn),dc=example,dc=com")
($dn) 宏与 dc=subdomain1,dc=hostedCompany1 匹配。
当 ACI 的主题也使用 ($dn) 时,与目标匹配的子字符串用于扩展主题。例如:
aci: (target="ldap:///ou=*,($dn),dc=example,dc=com") (targetattr = "*") (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,($dn),dc=example,dc=com";)
在这种情况下,如果目标中的字符串匹配 ($dn) 为 dc=subdomain1,dc=hostedCompany1,则主题中使用相同的字符串。然后,ACI 会扩展如下:
aci: (target="ldap:///ou=Groups,dc=subdomain1,dc=hostedCompany1, dc=example,dc=com") (targetattr = "*") (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups, dc=subdomain1,dc=hostedCompany1,dc=example,dc=com";)
扩展宏后,目录服务器会根据正常进程评估 ACI,以确定是否授予访问权限。
18.14.2.2. [$dn] 的宏匹配
[$dn] 的匹配机制与 $dn 稍有不同。目标资源的 DN 会多次检查,每次丢弃最旧的 RDN 组件时,直到找到匹配项为止。
例如,您有以 cn=all,ou=groups,dc=subdomain1,dc=hostedCompany1,dc=example,dc=com 子树为目标的 LDAP 请求,以及以下 ACI:
aci: (target="ldap:///ou=Groups,($dn),dc=example,dc=com") (targetattr = "*") (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,[$dn],dc=example,dc=com";)
扩展此 ACI 的步骤如下:
- ($DN) 匹配 dc=subdomain1,dc=hostedCompany1。
- 主题中的 [$DN] 替换为 dc=subdomain1,dc=hostedCompany1。结果为 groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=subdomain1,dc=hostedCompany1,dc=example,dc=com"。如果绑定 DN 是该组的成员,则匹配的进程将停止,并且评估 ACI。如果不匹配,该过程将继续。
- 主题中的 [$DN] 替换为 dc=hostedCompany1。结果为 groupdn="ldap:///cn=DomainAdmins,ou=Groups,dc=hostedCompany1,dc=example,dc=com"。在这种情况下,如果绑定 DN 不是该组的成员,则不会评估 ACI。如果是一个成员,则评估 ACI。
[$dn] 宏的优点是,它提供了为目录树中的所有子域授予域级别管理员访问权限的灵活方式。因此,表示域之间的分层关系非常有用。
例如,请考虑以下 ACI:
aci: (target="ldap:///ou=*, ($dn),dc=example,dc=com") (targetattr="*")(targetfilter=(objectClass=nsManagedDomain)) (version 3.0; acl "Domain access"; allow (read,search) groupdn="ldap:///cn=DomainAdmins,ou=Groups,[$dn],dc=example,dc=com";)
它为 dc=hostedCompany1 下的所有子域授予了访问 cn=DomainAdmins,ou=Groups,dc=hostedCompany1,dc=example,dc=com 成员的权限,因此属于那个组的管理员可以访问如 ou=people,dc=subdomain1.1,dc=subdomain1 的子树。
但是,同时,cn=DomainAdmins,ou=Groups,dc=subdomain1.1 的成员将被拒绝访问 ou=body,dc=hostedCompany1 和 ou=body,dc=subdomain1,dc=hostedCompany1 节点。
18.14.2.3. 宏匹配($attr.attrName)
DN 的主题部分始终使用 ($attr.attrName) 宏。例如,定义以下 roledn :
roledn = "ldap:///cn=DomainAdmins,($attr.ou)"
现在,假设服务器收到在以下条目的目标 LDAP 操作:
dn: cn=Jane Doe,ou=People,dc=HostedCompany1,dc=example,dc=com cn: Jane Doe sn: Doe ou: Engineering,dc=HostedCompany1,dc=example,dc=com ...
为了评估 ACI 的 roledn 部分,服务器将查看目标条目中存储的
ou
属性,并使用此属性的值来扩展宏。因此,在示例中,roledn 被扩展如下:
roledn = "ldap:///cn=DomainAdmins,ou=Engineering,dc=HostedCompany1,dc=example,dc=com"
然后目录服务器会根据普通的 ACI 评估算法评估 ACI。
当属性被多值时,每个值都会被用来扩展宏,第一个提供成功匹配项的值。例如:
dn: cn=Jane Doe,ou=People,dc=HostedCompany1,dc=example,dc=com cn: Jane Doe sn: Doe ou: Engineering,dc=HostedCompany1,dc=example,dc=com ou: People,dc=HostedCompany1,dc=example,dc=com...
在这种情况下,当 Directory 服务器评估 ACI 时,它会在以下扩展表达式上执行逻辑 OR :
roledn = "ldap:///cn=DomainAdmins,ou=Engineering,dc=HostedCompany1,dc=example,dc=com" roledn = "ldap:///cn=DomainAdmins,ou=People,dc=HostedCompany1,dc=example,dc=com"