基于规则的授权插件

Solr 提供授权插件,为关键 Solr API 和功能提供细粒度的用户访问控制。

Solr 的身份验证插件控制用户是否可以以二进制方式访问 Solr。用户要么经过身份验证,要么没有经过身份验证。对于更细粒度的访问控制,可以使用 Solr 的基于规则的授权插件 (RBAP)。

Solr 的管理 UI 使用其常规 API 与 Solr 交互。当使用基于规则的授权时,未经授权访问这些 API 全部范围的已登录用户可能会看到 UI 中一些显示为空白或“已损坏”的部分。

为了获得最佳效果,只有具有完全 API 访问权限的用户才能访问管理 UI。

基于规则的授权概念

“用户”、“角色”和“权限”在正确配置授权方面发挥着核心作用。

在基于规则的授权中,管理员根据他们希望这些角色授予的权限定义一系列角色。然后为用户分配一个或多个角色。

用户

RBAP 看到的用户来自已配置的任何身份验证插件。RBAP 与 Solr 随附的所有身份验证插件兼容。它还与用户可能编写的任何自定义身份验证插件兼容,前提是该插件在收到的 HttpServletRequest 上设置用户主体。

RBAP 在每种情况下看到的用户值取决于所使用的身份验证插件:如果正在使用Kerberos 身份验证插件,则为 Kerberos 主体;如果正在使用JWT 身份验证插件,则为“sub”JWT 声明,依此类推。

角色

角色弥补了用户和权限之间的差距。角色可以与任何身份验证插件或自定义身份验证插件(如果您已创建)一起使用。您只需要确保已登录的用户映射到插件定义的角色。

插件有两个实现,它们仅在获取用户角色的方式上有所不同

  • RuleBasedAuthorizationPlugin:角色到用户的映射必须在 security.json 中为每个可能的经过身份验证的用户明确定义。

  • ExternalRoleRuleBasedAuthorizationPlugin:角色到用户的映射在外部进行管理。此插件期望 AuthenticationPlugin 提供一个 Principal,该 Principal 还具有角色信息,并实现 VerifiedUserRoles 接口。

权限

权限控制哪些角色(以及哪些用户)可以访问哪些 Solr API。

每个权限有两个主要组成部分:权限适用的 API 描述,以及应该允许访问这组 API 的角色列表。

管理员可以使用预定义选项中的权限或定义自己的自定义权限,可以自由地混合和匹配两者。

配置基于规则的授权插件

与 Solr 的所有安全插件一样,RBAP 的配置位于名为 security.json 的文件或 ZooKeeper 节点中。请参阅 配置 security.json 了解更多有关如何在集群中设置 security.json 的信息。

Solr 提供了一个 授权 API 用于对 RBAP 配置进行更改。在大多数情况下,授权的管理员应该使用此 API 进行更改。如果 security.json 存储在 ZooKeeper 中,用户也可以直接对其进行编辑,但这是一种专家级功能,在大多数情况下不建议使用。该 API 简化了配置的某些方面,并提供了在直接编辑 ZooKeeper 时无法提供的错误反馈。

配置语法

RBAP 配置包含少量必需的配置属性。这些属性中的每一个都位于 security.json 中的 authorization 顶级属性下

class

必需

默认值:无

要使用的授权插件。有三个选项:solr.RuleBasedAuthorizationPluginsolr.ExternalRoleRuleBasedAuthorizationPluginsolr.MultiAuthRuleBasedAuthorizationPlugin

permissions

可选

默认值:无

用于限制对 Solr API 部分的访问的权限规则的 JSON 数组。例如

{
  "permissions": [
  { "name": "read", "collection": "techproducts", "role": ["admin", "dev"] },
  { "name": "all", "role": "admin"}
  ]
}

单个权限的语法更加复杂,将在 下面更详细地进行介绍。

当您为 class 使用 ExternalRoleRuleBasedAuthorizationPlugin 时,用户角色可能来自请求本身。在这种情况下,请跳过定义 permissions

如果您需要硬编码用户角色映射,请为 class 定义 RuleBasedAuthorizationPlugin,并在 security.json 中定义用户角色映射,如下所示

用户角色

可选

默认值:无

将单个用户映射到其分配的角色。此参数的值是 JSON 映射,其中每个属性名称是用户,每个属性值是指定用户所属的单个角色的名称或多个角色的 JSON 数组。

例如

{
  "user-role": {
  "user1": "role1",
  "user2": ["role1", "role2"]
  }
}
useShortName

可选

默认值:false

确定用户角色映射将使用完整主体还是身份验证插件提供的缩写名称进行解析。例如,KerberosAuthPlugin 可以将完整主体提供为 [email protected],而相应的缩写名称为 user

对于某些插件,主体名称和缩写名称可能相同。

RuleBasedAuthorizationPlugin 和 BasicAuth 的示例

此示例 security.json 展示了 Basic Authentication Plugin 如何与 RuleBasedAuthorizationPlugin 插件配合使用

{
  "authentication": {
    "class": "solr.BasicAuthPlugin", (1)
    "blockUnknown": true,
    "credentials": {
      "admin-user": "IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c=",
      "dev-user": "IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="
    }
  },
  "authorization": {
    "class": "solr.RuleBasedAuthorizationPlugin", (2)
    "user-role": { (3)
      "admin-user": "admin",
      "dev-user": "dev"
    },
    "permissions": [ (4)
      { "name": "dev-private-collection", "collection": "dev-private", "role": "dev"},
      { "name": "security-read", "role": "admin"},
      { "name": "security-edit", "role": "admin"}
    ]
  }
}
1 Solr 正在使用 Basic Authentication 插件进行身份验证。此配置建立了两个用户:admin-userdev-user
2 authorization 属性开始授权配置。Solr 将使用 RBAP 进行授权。
3 定义了两个角色:admindev。每个用户属于一个角色:admin-useradmindev-userdev
4 三个权限限制对 Solr 的访问。第一个权限(“自定义”权限)表示只有 dev 角色可以从名为 dev-private 的特殊集合中读取。最后两个权限(“预定义”权限)表示只有 admin 角色被允许使用 Solr 的安全 API。请参阅下文了解有关权限语法的更多信息。

总之,此示例划分了两个受限区域。只有 admin-user 可以访问 Solr 的身份验证和授权 API,只有 dev-user 可以访问其 dev-private 集合。所有其他 API 保持开放,两个用户都可以访问。

使用 JWT 身份验证的 External Role RuleBasedAuthorizationPlugin 示例

此示例 security.json 展示了 JWT 身份验证插件 如何工作,该插件从 JWT 声明中提取用户和用户角色,并且可以与 ExternalRoleRuleBasedAuthorizationPlugin 插件配合使用

{
"authentication":{
   "class": "solr.JWTAuthPlugin", (1)
   "jwksUrl": "https://my.key.server/jwk.json", (2)
   "rolesClaim": "roles" (3)
},
"authorization":{
   "class":"solr.ExternalRoleRuleBasedAuthorizationPlugin", (4)
   "permissions":[{"name":"security-edit",
      "role":"admin"}] (5)
}}

我们来了解一下此示例

1 JWT 身份验证插件已启用。
2 公钥将通过 HTTPS 提取。
3 我们希望每个 JWT 令牌都包含一个“角色”声明,该声明将传递给授权。
4 外部角色基于规则的授权插件已启用。
5 已定义“admin”角色,并且它具有编辑安全设置的权限。

只有来自具有角色“admin”的 JWT 令牌的请求才会被授予 security-edit 权限。

多个授权插件

如果您的 security.json 配置使用 MultiAuthPlugin,您需要使用 MultiAuthRuleBasedAuthorizationPlugin 为每个身份验证插件使用不同的授权插件。

以下示例说明如何使用 MultiAuthRuleBasedAuthorizationPluginBasicBearer 方案配置授权插件

{
  "authorization": {
    "class": "solr.MultiAuthRuleBasedAuthorizationPlugin",
    "schemes": [
      {
        "scheme": "basic",
        "class": "solr.RuleBasedAuthorizationPlugin",
        "user-role": {
          "k8s-oper": ["k8s"]
        }
      },
      {
        "scheme": "bearer",
        "class": "solr.ExternalRoleRuleBasedAuthorizationPlugin"
      }
    ],
    "permissions": []
  }
}

同一用户帐户在两个插件中同时存在的情况并不常见。但是,在确定用户的角色时,MultiAuthRuleBasedAuthorizationPlugin 会将所有插件中的角色合并在一起。

当使用基本身份验证时,用户应特别注意锁定服务帐户需要访问的确切端点集。例如,如果 MultiAuthPlugin 允许 k8s-oper 用户使用基本身份验证(而所有其他用户通过 OIDC),则为 k8s-oper 用户配置的权限应仅允许访问特定端点,例如 /admin/info/system

权限

Solr 的基于规则的授权插件支持灵活且强大的权限语法。RBAP 支持两种类型的权限,每种权限的语法略有不同。

自定义权限

管理员可以编写自己的自定义权限,这些权限可以根据集合、请求处理程序、HTTP 方法、特定请求参数等匹配请求。

每个自定义权限都是 permissions 参数下的一个 JSON 对象,具有以下一个或多个属性

name

可选

默认值:无

权限的标识符。

对于自定义权限,这仅用作管理员关于此权限的作用的线索。

设置此参数时必须小心,以避免与 Solr 的 预定义权限 冲突,这些权限的名称是保留的。如果此名称与预定义权限匹配,Solr 会忽略设置的任何其他属性,并改用预定义权限的语义。

collection

可选

默认值:*(全部)

定义权限适用的集合。该值可以是单个集合名称,也可以是包含多个集合的 JSON 数组。

通配符 * 用于指示此规则适用于所有集合。类似地,特殊值 null 可用于指示此权限管理 Solr 的与集合无关(“admin”)的 API。

collection 参数只能包含实际集合名称的值。它当前不能用于匹配别名。

+ 在调用 Solr 的安全插件之前解析别名。将别名作为值提供的 collection 参数永远不会匹配,因为 RBAP 会将别名与已解析的集合名称进行比较。

+ 相反,设置包含相关别名中所有集合(或 * 通配符)的 collection 参数。

path

可选

默认值:null

定义权限适用的路径。该值可以是单个路径字符串,也可以是包含多个字符串的 JSON 数组。

对于访问集合的 API,路径值应从集合名称后开始,通常看起来就像请求处理程序(例如,"/select")。

对于与集合无关(又名“admin”)的 API,路径值应从 "/admin 路径段开始。通配符 \* 可用于指示此权限适用于所有路径。

method

可选

默认值:*

定义此权限适用的 HTTP 方法。选项包括 HEADPOSTPUTGETDELETE 和通配符 \*。还可以使用 JSON 数组指定多个值。

params

可选

默认值:无

定义权限适用的查询参数。该值是一个 JSON 对象,其中包含必须匹配才能应用此权限的请求参数的名称和值。

例如,此参数可用于限制角色使用 Collections API 执行的操作。如果仅允许角色执行 LIST 或 CLUSTERSTATUS 请求,则可以按如下方式定义此参数

{"params": {
   "action": ["LIST", "CLUSTERSTATUS"]
   }
 }

请求参数值可以是简单字符串或正则表达式。使用前缀 REGEX: 使用正则表达式匹配而不是更简单的字符串匹配。

如果命令 LIST 和 CLUSTERSTATUS 不区分大小写,则可以按如下方式编写上面的示例

{"params": {
   "action": ["REGEX:(?i)LIST", "REGEX:(?i)CLUSTERSTATUS"]
 }
}
role

必需

默认值:无

定义哪些角色(或角色)可以访问此权限控制的 API。可以使用 JSON 数组指定多个值。通配符 * 可用于指示所有角色都可以访问所述功能。

预定义权限

自定义权限使管理员能够灵活地配置细粒度的访问控制。但是,为了尽可能简化配置,RBAP 还提供了一些预定义权限,涵盖了许多常见用例。

管理员通过选择与 Solr 的预定义权限选项之一(如下所列)匹配的 name 来调用预定义权限。Solr 为这些权限中的每一个都有自己的定义,并在检查预定义权限是否与传入请求匹配时使用此信息。这以简单性换取了灵活性:预定义权限不支持自定义权限允许的 pathparamsmethod 属性。

预定义权限名称(及其效果)是

  • security-edit:此权限允许编辑安全配置,这意味着将通过 API 修改 security.json 的任何更新操作都将被允许。

  • security-read:此权限允许读取安全配置,这意味着将允许通过 API 读取 security.json 设置的任何操作。

  • schema-edit:此权限允许使用 Schema API 编辑集合的架构。请注意,这允许对所有集合进行架构编辑权限。如果编辑权限应该仅应用于特定集合,则需要创建自定义权限。

  • schema-read:此权限允许使用 Schema API 读取集合的架构。请注意,这允许对所有集合进行架构读取权限。如果读取权限应该仅应用于特定集合,则需要创建自定义权限。

  • config-edit:此权限允许使用 Config APIRequest Parameters API 和修改 configoverlay.json 的其他 API 编辑集合的配置。由于配置 可以从各种位置添加库/自定义代码,因此明确允许具有此权限的用户通过受信任的 SolrConfig 加载任何新代码。请注意,这允许对所有集合进行配置编辑权限。如果编辑权限应该仅应用于特定集合,则需要创建自定义权限。

  • config-read:此权限允许使用 Config APIRequest Parameters APIConfigsets API、Admin UI 的 文件屏幕 和访问配置的其他 API 读取集合的配置。请注意,这允许对所有集合进行配置读取权限。如果读取权限应该仅应用于特定集合,则需要创建自定义权限。

  • metrics-read:此权限允许访问 Solr 的 Metrics API、一些 隐式管理程序,例如 solr/<collection>/admin/mbeanssolr/<collection>/admin/segments,以及公开指标的其他管理 API。

  • health:此权限允许访问 Solr 的 运行状况检查和 ping 端点,通常用于监视节点或内核是否正常。

  • core-admin-edit:可以改变系统状态的核心管理命令。

  • core-admin-read:核心管理 API 上的读取操作

  • collection-admin-edit:此权限允许使用 集合 API 编辑集合的配置。请注意,这允许对所有集合进行配置编辑权限。如果编辑权限应该仅应用于特定集合,则需要创建自定义权限。

    具体来说,允许集合 API 的以下操作

    CREATE

    RELOAD

    SPLITSHARD

    CREATESHARD

    DELETESHARD

    CREATEALIAS

    DELETEALIAS

    DELETE

    DELETEREPLICA

    ADDREPLICA

    CLUSTERPROP

    MIGRATE

    ADDROLE

    REMOVEROLE

    ADDREPLICAPROP

    DELETEREPLICAPROP

    BALANCESHARDUNIQUE

    REBALANCELEADERS

  • collection-admin-read:此权限允许使用 集合 API 读取集合的配置。请注意,这允许对所有集合进行配置读取权限。如果读取权限应该仅应用于特定集合,则需要创建自定义权限。

    具体来说,允许集合 API 的以下操作

    LIST

    OVERSEERSTATUS

    CLUSTERSTATUS

    REQUESTSTATUS

  • update:此权限允许对任何集合执行任何更新操作。这包括发送文档以进行索引(使用 更新请求处理程序)。默认情况下,这适用于所有集合(collection:"*")。

  • read:此权限允许对任何集合执行任何读取操作。这包括使用搜索处理程序(使用 请求处理程序)进行查询,例如 /select/get/tvrh/terms/clustering/elevate/export/spell/clustering/sql。默认情况下,这适用于所有集合(collection:"*")。

  • zk-read:从 ZK 读取内容的权限(/api/cluster/zk/data//api/cluster/zk/ls/

  • all:发送到 Solr 的任何请求。

权限排序和解析

上述讨论的权限语法无法防止多个权限重叠并应用于同一 Solr API。在多个权限与传入请求匹配的情况下,Solr 会选择第一个匹配的权限并忽略所有其他权限,即使这些其他权限与传入请求匹配!

由于 Solr 仅使用找到的第一个匹配权限,因此管理员了解 Solr 在处理权限列表时使用的排序非常重要。

Solr 使用的排序很复杂。Solr 首先尝试检查任何与传入请求特定或相关的权限,只有在没有更具体的权限匹配时才继续检查更通用的权限。实际上,这意味着不同的请求可能会以非常不同的顺序检查相同的权限。

如果传入请求与集合无关(不适用于特定集合),Solr 将按以下顺序检查权限

  1. collection 值为 nullpath 值与请求的请求处理程序匹配的权限

  2. collection 值为 nullpath 值为 * 的权限

  3. collection 值为 nullpath 值为 null 的权限

如果传入请求是针对集合的,Solr 将按以下顺序检查权限

  1. collectionpath 值与请求具体匹配(不是通配符匹配)的权限

  2. collection 与请求具体匹配,且 path 值为 * 的权限

  3. collection 与请求具体匹配,且 path 值为 null 的权限

  4. path 与请求具体匹配,且 collection 值为 * 的权限

  5. collectionpath 值均为 * 的权限。

  6. collection 值为 *path 值为 null 的权限

例如,考虑以下权限

{"name": "read", "role": "dev"}, (1)
{"name": "coll-read", "path": "/select", "role": "*"}, (2)
{"name": "techproducts-read", "collection": "techproducts", "role": "other", "path": "/select"}, (3)
{"name": "all", "role": "admin"} (4)

此列表中的所有权限都与 /select 查询匹配。但将根据要查询的集合使用不同的权限。

对于对“techproducts”集合的查询,将使用权限 3,因为它专门针对“techproducts”。只有具有other角色的用户将被授权。

另一方面,对于对名为collection1的集合的查询,最具体的权限是权限 2,因此所有角色都被授予访问权限。

授权 API

授权 API 端点

/admin/authorization:采用一组命令来创建权限、将权限映射到角色,并将角色映射到用户。

管理权限

三个命令控制管理权限

  • set-permission:创建新权限、覆盖现有权限定义或将预定义权限分配给角色。

  • update-permission:更新现有权限定义的一些属性。

  • delete-permission:删除权限定义。

创建的属性可以是自定义的,也可以是预定义的。

除了上面讨论的权限语法之外,这些命令还允许权限具有before属性,其值与此新权限在security.json中应排在其之前的权限的索引匹配。

以下内容创建一个名为“collection-mgr”的新权限,该权限允许创建和列出集合。此权限将排在“read”权限之前。另请注意,我们已将collection定义为null,因为对集合 API 的请求从不特定于集合。

curl --user solr:SolrRocks -H 'Content-type:application/json' -d '{
  "set-permission": {"collection": null,
                     "path":"/admin/collections",
                     "params":{"action":["LIST", "CREATE"]},
                     "before": 3,
                     "role": "admin"}
}' http://localhost:8983/solr/admin/authorization

对所有集合应用更新权限,对名为dev的角色应用更新权限,对名为guest的角色应用读取权限

curl --user solr:SolrRocks -H 'Content-type:application/json' -d '{
  "set-permission": {"name": "update", "role":"dev"},
  "set-permission": {"name": "read", "role":"guest"}
}' http://localhost:8983/solr/admin/authorization

更新或删除权限

可以使用权限在列表中的索引来访问权限。使用/admin/authorization API 查看现有权限及其索引。

以下示例更新索引为3的权限的'role'属性

curl --user solr:SolrRocks -H 'Content-type:application/json' -d '{
  "update-permission": {"index": 3,
                       "role": ["admin", "dev"]}
}' http://localhost:8983/solr/admin/authorization

以下示例删除索引为3的权限

curl --user solr:SolrRocks -H 'Content-type:application/json' -d '{
  "delete-permission": 3
}' http://localhost:8983/solr/admin/authorization

将角色映射到用户

单个命令允许将角色映射到用户

  • set-user-role:将用户映射到权限。

要删除用户的权限,应将角色设置为null。没有命令可以删除用户角色。

提供给命令的值只是用户 ID 和用户应该拥有的一个或多个角色。

例如,以下命令将授予用户“solr”角色“admin”和“dev”,并从用户 ID“harry”中删除所有角色

curl -u solr:SolrRocks -H 'Content-type:application/json' -d '{
   "set-user-role" : {"solr": ["admin","dev"],
                      "harry": null}
}' http://localhost:8983/solr/admin/authorization