映射 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 继承链的评估决策顺序是:先评估叶项及其父项,然后一直向下评估到根项。

删除包含关系和项

将项编入索引时,您可以使用 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。