Kerberos 身份验证插件

如果您使用 Kerberos 来保护您的网络环境,则可以使用 Kerberos 身份验证插件来保护 Solr 集群。

这允许 Solr 使用 Kerberos 服务主体和 keytab 文件与 ZooKeeper 以及 Solr 集群的节点之间(如果适用)进行身份验证。Admin UI 的用户和所有客户端(例如 SolrJ)也需要在能够使用 UI 或向 Solr 发送请求之前拥有有效的票证。

SolrCloud、用户管理或单节点安装中均支持 Kerberos 身份验证。

如果您正在使用带有 Kerberos 保护的 Hadoop 集群中的 Solr,并打算将 Solr 索引存储在 HDFS 中,请参阅 HDFS 上的 Solr 部分,了解为该目的配置 Solr 的其他步骤。此页面上的说明仅适用于 Solr 将使用 Kerberos 进行保护的场景。如果您只需要将索引存储在 Kerberized HDFS 系统中,请参阅在 HDFS 上运行 Solr 部分。

Solr 如何与 Kerberos 协同工作

在设置 Solr 以使用 Kerberos 时,会进行配置,以便 Solr 使用服务主体或 Kerberos 用户名,该用户名在密钥分发中心 (KDC) 注册以验证请求。这些配置定义了服务主体名称和包含凭据的 keytab 文件的位置。

与所有身份验证插件一样,Kerberos 身份验证配置存储在 security.json 中。此文件在 配置 security.json 部分中讨论。

服务主体和 Keytab 文件

每个 Solr 节点必须有一个在密钥分发中心 (KDC) 注册的服务主体。Kerberos 插件使用 SPNego 来协商身份验证。

HTTP/[email protected] 作为服务主体的示例

  • HTTP 指示将使用此服务主体进行身份验证的请求类型。服务主体中的 HTTP/ 对于 SPNego 与通过 HTTP 向 Solr 发出的请求一起工作是必须的。

  • host1 是托管 Solr 节点的机器的主机名。

  • YOUR-DOMAIN.ORG 是组织范围的 Kerberos 领域。

同一主机上的多个 Solr 节点可能具有相同的服务主体,因为主机名对于它们都是通用的。

除了服务主体之外,每个 Solr 节点还需要一个 keytab 文件,该文件应包含所用服务主体的凭据。keytab 文件包含加密的凭据,以支持在从 KDC 获取 Kerberos 票证时进行无密码登录。对于每个 Solr 节点,keytab 文件应保存在安全的位置,并且不与集群的用户共享。

由于 Solr 集群需要节点间通信,因此每个节点还必须能够向其他节点发出启用 Kerberos 的请求。默认情况下,Solr 使用与“客户端主体”相同的服务主体和密钥表进行节点间通信。您可以显式配置不同的客户端主体,但不建议这样做,并且以下示例中不涉及。

启用 Kerberos 的 ZooKeeper

在设置启用 Kerberos 的 SolrCloud 集群时,建议也为 ZooKeeper 启用 Kerberos 安全性。

在这种设置中,用于向 ZooKeeper 验证请求的客户端主体也可以共享用于节点间通信。这样做的好处是不需要单独更新票据授予票据 (TGT),因为 Solr 使用的 ZooKeeper 客户端会处理此问题。为了实现这一点,Kerberos 插件和 ZooKeeper 客户端可以使用单个 JAAS 配置(应用程序名称为 Client)。

有关在 Kerberos 模式下启动 ZooKeeper 的示例,请参见下面的ZooKeeper 配置部分。

浏览器配置

为了使您的浏览器在启用 Kerberos 身份验证后能够访问 Solr 管理 UI,它必须能够与 Kerberos 身份验证器服务协商以允许您访问。每个浏览器对此的支持方式都不同,有些(如 Chrome)根本不支持。如果在启用 Kerberos 身份验证后尝试访问 Solr 管理 UI 时看到 401 错误,则很可能是您的浏览器未正确配置,不知道如何或在何处协商身份验证请求。

有关如何设置浏览器的详细信息超出了本文档的范围;有关如何配置浏览器的详细信息,请咨询您的系统管理员有关 Kerberos 的信息。

Kerberos 身份验证配置

咨询您的 Kerberos 管理员!

在尝试配置 Solr 以使用 Kerberos 身份验证之前,请查看下面概述的每个步骤,并就每个详细信息咨询您当地的 Kerberos 管理员,以确保您知道每个参数的正确值。小错误可能会导致 Solr 无法启动或无法正常运行,并且很难诊断。

Kerberos 插件的配置有几个部分

  • 创建服务主体和密钥表文件

  • ZooKeeper 配置

  • 创建或更新 /security.json

  • 定义 jaas-client.conf

  • Solr 启动参数

我们将在下面逐步介绍这些步骤。

使用主机名

要使用主机名而不是 IP 地址,请在 bin/solr.in.sh 中使用 SOLR_HOST 配置,或者在 Solr 启动期间传递 -Dhost=<hostname> 系统参数。本指南使用 IP 地址。如果您指定主机名,请将指南中的所有 IP 地址替换为相应 Solr 主机名。

获取服务主体和密钥表

在配置 Solr 之前,请确保您在 KDC 服务器中为每个 Solr 主机和 ZooKeeper(如果尚未配置 ZooKeeper)提供 Kerberos 服务主体,并生成如下所示的密钥表文件。

此示例假设主机名为 192.168.0.107,并且您的主目录是 /home/foo/。此示例应根据您自己的环境进行修改。

root@kdc:/# kadmin.local
Authenticating as principal foo/[email protected] with password.

kadmin.local:  addprinc HTTP/192.168.0.107
WARNING: no policy specified for HTTP/[email protected]; defaulting to no policy
Enter password for principal "HTTP/[email protected]":
Re-enter password for principal "HTTP/[email protected]":
Principal "HTTP/[email protected]" created.

kadmin.local:  ktadd -k /tmp/107.keytab HTTP/192.168.0.107
Entry for principal HTTP/192.168.0.107 with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/tmp/107.keytab.
Entry for principal HTTP/192.168.0.107 with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/tmp/107.keytab.
Entry for principal HTTP/192.168.0.107 with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/tmp/108.keytab.
Entry for principal HTTP/192.168.0.107 with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/tmp/107.keytab.

kadmin.local:  quit

将密钥表文件从 KDC 服务器的 /tmp/107.keytab 位置复制到 Solr 主机上的 /keytabs/107.keytab。为每个 Solr 节点重复此步骤。

如果尚未设置,您可能需要采取类似步骤来创建 ZooKeeper 服务主体和密钥表。在这种情况下,下面的示例显示了 ZooKeeper 的不同服务主体,因此上述步骤可能会重复,其中 zookeeper/host1 作为其中一个节点的请求服务主体

ZooKeeper 配置

如果您正在使用已配置为使用 Kerberos 的 ZooKeeper,则可以跳过此处显示的与 ZooKeeper 相关的步骤。

由于 ZooKeeper 管理 SolrCloud 集群中节点之间的通信,因此它还必须能够与集群的每个节点进行身份验证。配置需要为 ZooKeeper 设置服务主体,定义 JAAS 配置文件,并指示 ZooKeeper 使用这两个项目。

第一步是在 ZooKeeper 的 conf 目录中创建一个 java.env 文件,并将以下内容添加到其中,如下例所示

export JVMFLAGS="-Djava.security.auth.login.config=/etc/zookeeper/conf/jaas-client.conf"

JAAS 配置文件应包含以下参数。请务必根据需要更改 principalkeyTab 路径。该文件必须位于上述步骤中定义的路径中,并指定文件名。

Server {
 com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/keytabs/zkhost1.keytab"
  storeKey=true
  doNotPrompt=true
  useTicketCache=false
  debug=true
  principal="zookeeper/[email protected]";
};

最后,将以下行添加到 ZooKeeper 配置文件 zoo.cfg

authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000

完成所有设置后,使用指向 JAAS 配置文件的以下参数启动 ZooKeeper

$ bin/zkServer.sh start -Djava.security.auth.login.config=/etc/zookeeper/conf/jaas-client.conf

创建 security.json

创建文件 security.json,内容如下

{"authentication": {"class": "solr.KerberosPlugin"}}

然后使用 bin/solr zk 命令上传文件

$ bin/solr zk cp ./security.json zk:security.json -z localhost:2181

如果您在单节点安装中使用 Solr,则需要创建 security.json 文件并将其放在 $SOLR_HOME 目录中。

如果 ZooKeeper 中已存在 /security.json 文件,请下载该文件,添加或修改身份验证部分,然后使用 Solr 中提供的ZooKeeper 实用程序将其上传回 ZooKeeper。

定义 JAAS 配置文件

JAAS 配置文件定义了用于身份验证的属性,例如服务主体和密钥表文件的位置。还可以设置其他属性,以确保票据缓存和其他功能。

可以复制以下示例,并根据您的环境稍作修改。该文件的位置可以在服务器上的任何位置,但是在启动 Solr 时会引用该文件,因此它必须在文件系统上可读。JAAS 文件可能包含多个不同用户的部分,但是每个部分都必须具有唯一的名称,以便可以在每个应用程序中唯一引用它。

在下面的示例中,我们创建了一个 JAAS 配置文件,名称和路径为 /home/foo/jaas-client.conf。在下一部分中定义 Solr 启动参数时,我们将使用此名称和路径。请注意,此处的客户端 principal 与服务主体相同。这将用于验证节点间请求和对 ZooKeeper 的请求。请确保使用正确的主机名 principalkeyTab 文件路径。

Client {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/keytabs/107.keytab"
  storeKey=true
  useTicketCache=true
  debug=true
  principal="HTTP/[email protected]";
};

此文件的第一行定义了节名称,该节名称将与下面定义的 solr.kerberos.jaas.appname 参数一起使用。

我们主要关注的属性是 keyTabprincipal 属性,但是您的环境可能还需要其他属性。Krb5LoginModule 的 javadocs(正在使用并在上面第二行中调用的类)提供了可用属性的良好概述,但是为了方便参考,此处解释了上述示例中正在使用的属性

  • useKeyTab:此布尔属性定义是否应使用密钥表文件(在本例中为 true)。

  • keyTab:此 JAAS 配置文件部分所针对的主体的密钥表文件的位置和名称。路径应该用双引号括起来。

  • storeKey:此布尔属性允许将密钥存储在用户的私有凭据中。

  • useTicketCache:此布尔属性允许从票据缓存中获取票据。

  • debug:此布尔属性将输出调试消息以帮助进行故障排除。

  • principal:要使用的服务主体的名称。

Solr 启动参数

在启动 Solr 时,需要传递以下特定于主机的参数。这些参数可以使用 bin/solr start 命令在命令行中传递(有关如何传递系统参数的详细信息,请参阅Solr 控制脚本参考),或者在 bin/solr.in.shbin/solr.in.cmd 中定义,具体取决于您的操作系统。

solr.kerberos.name.rules

可选

默认值:DEFAULT

用于将 Kerberos 主体映射到短名称。名称规则的示例:RULE:[1:$1@$0](.*EXAMPLE.COM)s/@.*//

solr.kerberos.name.rules.mechanism

可选

默认值:hadoop

用于将 Kerberos 主体映射到短名称的机制。可以是 hadoopmit

solr.kerberos.cookie.domain

必需

默认值:无

用于颁发 Cookie,应具有 Solr 节点的主机名。

solr.kerberos.cookie.portaware

可选

默认值:false

设置为 true 时,Cookie 会根据主机和端口进行区分,而不是不感知端口的标准 Cookie。如果同一主机上托管了多个 Solr 节点,则应进行设置。

solr.kerberos.principal

必需

默认值:无

服务主体。

solr.kerberos.keytab

必需

默认值:无

包含服务主体凭据的密钥表文件路径

solr.kerberos.jaas.appname

可选

默认值:Client

JAAS 配置文件中的应用程序名称(节名称),这是节点间通信所必需的。默认值也用于 ZooKeeper 身份验证。如果 ZooKeeper 和 Solr 使用不同的用户,则它们需要在 JAAS 配置文件中具有单独的部分。

java.security.auth.login.config

必需

默认值:无

用于为节点间通信配置 Solr 客户端的 JAAS 配置文件的路径。

以下是一个可以添加到 bin/solr.in.sh 的示例。请务必更改此示例以使用正确的主机名和密钥表文件路径。

SOLR_AUTH_TYPE="kerberos"
SOLR_AUTHENTICATION_OPTS="-Djava.security.auth.login.config=/home/foo/jaas-client.conf -Dsolr.kerberos.cookie.domain=192.168.0.107 -Dsolr.kerberos.cookie.portaware=true -Dsolr.kerberos.principal=HTTP/[email protected] -Dsolr.kerberos.keytab=/keytabs/107.keytab"
使用 AES-256 加密的 KDC

如果您的 KDC 使用 AES-256 加密,则需要在启用 Kerberos 的 Solr 与 KDC 交互之前,将 Java 加密扩展 (JCE) 无限制强度管辖策略文件添加到您的 JRE。

当您在 Solr 日志中看到类似这样的错误时,您就会知道问题所在:“KrbException: Encryption type AES256 CTS mode with HMAC SHA1-96 is not supported/enabled”。

JAVA_HOME/jre/lib/security/ 中的 local_policy.jar 替换为从下载包中获取的新的 local_policy.jar,然后重启 Solr 节点。

使用委托令牌

可以配置 Kerberos 插件以使用委托令牌,这允许应用程序重用最终用户或其他应用程序的身份验证。

Solr 中有几种可以使用此功能的场景:

  • 使用分布式客户端(例如 MapReduce),每个客户端可能无法访问用户的凭据。

  • 当 Kerberos 服务器上的负载很高时。委托令牌可以减少负载,因为它们在第一次请求后不会访问服务器。

  • 如果需要将请求或权限委派给另一个用户。

要启用委托令牌,必须定义几个参数。这些参数可以通过 bin/solr 启动命令的命令行传递(请参阅Solr 控制脚本参考),或者在 bin/solr.in.shbin/solr.in.cmd 中定义,具体取决于您的操作系统。

solr.kerberos.delegation.token.enabled

可选

默认值:false

设置为 true 以启用委托令牌。如果您想启用令牌,则此参数是必需的。

solr.kerberos.delegation.token.kind

可选

默认值:solr-dt

委托令牌的类型。目前唯一可用的选项是默认值。

solr.kerberos.delegation.token.validity

可选

默认值:36000

委托令牌的有效时间,以秒为单位。

solr.kerberos.delegation.token.signer.secret.provider

可选

默认值:zookeeper

内部存储委托令牌信息的位置。默认值为 zookeeper,它必须是委托令牌在 Solr 服务器之间(在 SolrCloud 模式下运行时)工作的 Location。目前没有其他选项可用。

solr.kerberos.delegation.token.signer.secret.provider.zookeper.path

可选

默认值:无

存储密钥提供程序信息的 ZooKeeper 路径。其格式为路径 + /security/token。该路径可以包含 chroot,如果您不使用 chroot,也可以省略它。此示例包含 chroot:server1:9983,server2:9983,server3:9983/solr/security/token

solr.kerberos.delegation.token.secret.manager.znode.working.path

可选

默认值:无

存储令牌信息的 ZooKeeper 路径。其格式为路径 + /security/zkdtsm。该路径可以包含 chroot,如果您不使用 chroot,也可以省略它。此示例包含 chroot:server1:9983,server2:9983,server3:9983/solr/security/zkdtsm

启动 Solr

配置完成后,您可以使用 bin/solr 脚本启动 Solr,如下例所示,该示例仅适用于 SolrCloud 模式下的用户。

此示例假设您已使用正确的值修改了 bin/solr.in.shbin/solr.in.cmd,但如果您没有修改,则需要将系统参数与启动命令一起传递。请注意,您还需要根据 ZooKeeper 节点的位置自定义 -z 属性。

$ bin/solr start -c -z server1:2181,server2:2181,server3:2181/solr
如果您已在 solr.in.sh/solr.in.cmd 中定义了 ZK_HOST(请参阅更新 Solr 包含文件),则可以从上述命令中省略 -z <zk host string>

测试配置

  1. 使用您的用户名执行 kinit。例如,kinit [email protected]

  2. 尝试使用 curl 访问 Solr。您应该收到成功的响应。

    $ curl --negotiate -u : "http://192.168.0.107:8983/solr/"

将 SolrJ 与 Kerberos 化的 Solr 结合使用

要在 SolrJ 应用程序中使用 Kerberos 身份验证,您需要在创建 SolrClient 之前使用以下两行代码

System.setProperty("java.security.auth.login.config", "/home/foo/jaas-client.conf");
HttpClientUtil.setHttpClientBuilder(new Krb5HttpClientBuilder().getBuilder());

您需要在上面的 JAAS 客户端配置文件中为客户端指定 Kerberos 服务主体和相应的 keytab。此主体应与我们为 Solr 创建的服务主体不同。

这是一个例子

SolrJClient {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/keytabs/foo.keytab"
  storeKey=true
  useTicketCache=true
  debug=true
  principal="[email protected]";
};

SolrJ 的委托令牌

SolrJ 也支持委托令牌,方式如下:

  • DelegationTokenRequestDelegationTokenResponse 可用于获取、取消和续订委托令牌。

  • HttpSolrClient.Builder 包括一个 withKerberosDelegationToken 函数,用于创建使用委托令牌进行身份验证的 HttpSolrClient。

获取委托令牌的示例代码

private String getDelegationToken(final String renewer, final String user, HttpSolrClient solrClient) throws Exception {
    DelegationTokenRequest.Get get = new DelegationTokenRequest.Get(renewer) {
      @Override
      public SolrParams getParams() {
        ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
        params.set("user", user);
        return params;
      }
    };
    DelegationTokenResponse.Get getResponse = get.process(solrClient);
    return getResponse.getDelegationToken();
  }

创建使用委托令牌的 HttpSolrClient

HttpSolrClient client = new HttpSolrClient.Builder("https://127.0.0.1:8983/solr").withKerberosDelegationToken(token).build();

创建使用委托令牌的 CloudSolrClient

CloudSolrClient client = new CloudSolrClient.Builder(Collections.singletonList("localhost:2181"),Optional.empty())
                .withLBHttpSolrClientBuilder(new LBHttpSolrClient.Builder()
                    .withResponseParser(client.getParser())
                    .withHttpSolrClientBuilder(
                        new HttpSolrClient.Builder()
                            .withKerberosDelegationToken(token)
                    ))
                        .build();

Hadoop 的委托令牌响应采用 JSON map 格式。DelegationTokenResponse 中提供了该格式的响应解析器。其他响应解析器可能无法很好地处理 Hadoop 响应。