基于规则的授权插件

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

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

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

为了获得最佳效果,管理用户界面应仅由具有完整 API 访问权限的用户访问。

基于规则的身份验证概念

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

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

用户

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"}
  ]
}

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

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

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

user-role

可选

默认值:无

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

例如

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

可选

默认值:false

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

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

RuleBasedAuthorizationPlugin 和 BasicAuth 的示例

此示例 security.json 显示了 基本身份验证插件 如何与 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 使用基本身份验证插件进行身份验证。 此配置建立了两个用户:admin-userdev-user
2 authorization 属性开始授权配置。 Solr 将使用 RBAP 进行授权。
3 定义了两个角色:admindev。 每个用户都属于一个角色:admin-user 是一个 admin,而 dev-user 是一个 dev
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:此权限允许使用配置 API请求参数 API以及其他修改 configoverlay.json 的 API 编辑集合的配置。由于配置可以从各种位置添加库/自定义代码,因此,对于具有此权限的用户,明确允许通过受信任的 SolrConfig 加载任何新代码。请注意,这允许对所有集合进行配置编辑权限。如果编辑权限应该仅应用于特定集合,则需要创建自定义权限。

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

  • metrics-read:此权限允许访问 Solr 的指标 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"}
}' https://127.0.0.1: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"}
}' https://127.0.0.1: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"]}
}' https://127.0.0.1:8983/solr/admin/authorization

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

curl --user solr:SolrRocks -H 'Content-type:application/json' -d '{
  "delete-permission": 3
}' https://127.0.0.1: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}
}' https://127.0.0.1:8983/solr/admin/authorization