映射 ACL

为了确保只有有权访问某项的用户才能在搜索结果中看到该项,您应该使用企业代码库中的访问控制列表 (ACL) 将项编入索引。您必须为代码库的 ACL 建模,并在为代码库中的项编制索引时包含这些 ACL。内容连接器 SDK 提供了一组丰富的 ACL 方法,足以为大多数代码库的 ACL 建模。

创建 ACL

创建 ACL 的过程分为两个步骤:

  1. 使用 ACL 类中的静态方法创建 Principal
  2. 使用 Acl.Builder 类,通过主帐号构建 ACL。

本文档的其余部分将介绍对 ACL 建模和创建 ACL 时需要了解的一些概念,例如继承和包含。

使用外部 ID 创建主账号

Google Cloud Search 要求将用户和群组解析为 Google 电子邮件地址。将代码库项编入索引时,内容连接器可能没有这些电子邮件地址。但是,内容连接器 SDK 允许您使用任何外部 ID(授予用户或群组对代码库项的访问权限的 ID)而不是电子邮件地址来将项编入索引。使用 getUserPrincipal() 方法或 getGroupPrincpal() 方法创建包含外部 ID 的主帐号。ACL 类中还有其他几种静态方法,这些方法用于构建 Principal 对象。

ACL 继承

ACL 继承是指针对某个特定项和某个特定用户的授权,该授权依据的是该项的 ACL 及其继承链的 ACL 的合并结果。用于做出授权决策的规则取决于代码库和项的属性。

设置继承

每个项目都可以具有“直接允许的主帐号”和“直接拒绝的主帐号”,分别使用 setReaders()setDeniedReaders() 方法指定。“直接允许的主账号”是指在 ACL 中标识为能够直接访问特定项的用户。“直接拒绝的主账号”是指在 ACL 中标识为无权访问特定项的用户。

一项内容还可以使用 setInheritFrom() 方法继承“间接允许的主帐号”“间接拒绝的主帐号”。“间接允许的主账号”是指能够通过 ACL 继承来间接访问特定项的用户。“间接拒绝的主账号”是指被拒绝通过 ACL 继承来访问特定项的用户。

图 1 显示了如何使用 setInheritFrom() 方法继承“间接允许”和“间接拒绝”的主帐号。

展示各个项之间的关联的图片
图 1. setInheritFrom() 方法。

图 1 表示了以下访问控制:

  • 用户 1 是项 A 的“直接允许的主账号”。
  • 用户 2 是项 B 的“直接允许的主账号”。
  • 项 B 继承项 A 的 ACL。

根据访问控制,访问规则如下:

  • 用户 1 无需明确指定为项 B 的主账号即可成为项 B 的“间接允许的主账号”;用户 1 会继承访问权限,因为其被列为项 A 的“直接允许的主账号”,而项 B 则从项 A 继承其 ACL。
  • 用户 2 不是项 A 的“间接允许的主账号”。

设置继承类型

如果您使用 setInheritFrom() 方法设置继承类型,则必须使用 setInheritanceType() 方法设置继承类型。继承类型决定了子项的 ACL 与其父项的 ACL 的合并方式。Acl.InheritanceType 实现了三种继承类型:

  • BOTH_PERMIT - 如果将继承类型设置为 BOTH_PERMIT,则只有在子项的 ACL 和父项的继承项 ACL 都允许某个用户访问该项时,系统才会授予该用户对该项的访问权限。

  • CHILD_OVERRIDE - 如果将继承类型设置为 CHILD_OVERRIDE,则在发生冲突时,系统会强制使子项的 ACL 优先于继承的父项的 ACL。因此,当父项的 ACL 拒绝用户以被拒读取者身份进行访问时,如果用户能够以读取者身份访问子项,则用户仍然可以进行访问。相反,如果用户是子项的被拒读取者,则即使父项的 ACL 授予用户访问权限,用户也无法进行访问。

  • PARENT_OVERRIDE - 如果将继承类型设置为 PARENT_OVERRIDE,则在发生冲突时,系统会强制使父项的 ACL 优先于子项的 ACL。因此,当子项的 ACL 拒绝用户以被拒读取者身份进行访问时,如果用户能够以读取者身份访问父项,则用户仍然可以进行访问。相反,如果用户是父项的被拒读取者,则即使子项的 ACL 授予用户访问权限,用户也无法进行访问。

在评估 ACL 继承链时,授权决策的结果可能会因评估的顺序而发生变化。Cloud Search 按照从叶到根的顺序评估 ACL 继承链。具体而言,针对链的 ACL 决策从评估其父项的子项开始,一直延伸到根父项。

例如,如果子级的继承类型为 CHILD_OVERRIDE,并且用户有权访问子级,则云端硬盘不需要评估父级。但是,如果子级具有 PARENT_OVERRIDE 或 BOTH_PERMIT,则云端硬盘会继续评估链中的后续继承关系。

删除包含关系和项

将项编入索引时,您可以使用 IndexingItemBuilder 类的 setContainer() 方法将项标记为容器。容器与容器之间的关系用于建立项的物理层次结构,并确保正确删除项。当容器被删除时,它所包含的项也会被删除。

包含关系完全独立于 ACL 继承规则。 例如,文件系统中的某个文件可以包含在文件夹中以便删除,但可以从其他文件夹继承 ACL。删除某个文件夹时,系统不会删除继承其 ACL 的项,除非这些项也在该文件夹的包含层次结构中。

图 2 表示了以下访问控制关系:

  • 用户 1 是项 A 的“直接允许的主账号”。
  • 用户 2 是项 B 的“直接允许的主账号”。
  • 用户 3 是项 C 的“直接允许的主账号”。
  • 项 C 继承项 A 的 ACL。
  • 项 B 指定项 A 作为其容器。
  • 项 C 指定项 B 作为其容器。

根据访问控制,访问规则如下:

  • 间接访问是通过 setInheritFrom() 方法进行的。因此,用户 1 可以访问项 C,因为项 C 继承了项 A 的 ACL。
  • 间接访问不是通过项 B 包含的项 C 进行的。因此,用户 2 无法访问项 C。
展示各个项之间的关联的图片
图 2.正在使用的 setInheritFrom() 方法。

通过将 ACL 继承与包含层次结构分离开来,您可以对许多不同的现有结构进行建模。

成功删除项以后的情况如下:

  • 包含被删除项的任何项都将无法搜索,并且系统会安排从 Google 的数据源将其删除。
  • 使用 setInheritFrom() 方法指定了被删除项的任何项都将无法搜索。

如果资源使用 setInheritFrom() 方法具有已删除的项,但没有使用 setContainer() 的容器集,或者其包含层次结构不包含已删除项,则该项及其数据会保留在 Google 的数据源中。您将负责删除该项。

图 3 显示了删除操作在项的层次结构中的工作方式。

展示各个项之间的关联的图片
图 3. 删除项和 ACL 继承。

图 3 表示了以下访问控制关系:

  • 用户 1 是项 A 的“直接允许的主账号”。
  • 用户 2 是项 D 的“直接允许的主账号”。
  • 项 D 和项 E 都继承了项 A 的 ACL。
  • 项 D 指定项 A 作为其容器。
  • 项 A 和项 E 是根级项,因为它们没有容器项。

删除操作通过容器引用进行级联。删除项 A 以后的情况如下:

  • setInheritFrom() 引用的所有后代都会失去所有用户的访问权限。
  • 任何用户都无法访问项 A。
  • 系统会隐式删除项 D。任何用户都无法访问项 D。
  • 系统不会删除项 E,因为删除操作仅通过容器引用进行级联。
  • 无法访问项 E,且任何用户都无法搜索项 E。