Solr集成kerberos認證


1. 概述

  solr使用kerberos principal和keytab文件來認證zookeeper和solr集群。kerberos認證插件僅僅在solrcloud模式下有用。

  當設置solr使用kerberos的時候,一個在KDC中注冊認證的服務principal或者kerberos用戶名的配置是需要的。這個配置定義了服務主體的名稱和keytab文件的位置。solr的認證模式是用security.json這個文件,如果更改這個文件,需要重啟整個solr集群。此外認證插件可以通過系統啟動參數制定:-DauthenticationPlugin=org.apache.solr.security.KerberosPlugin。這個參數可以用在solrcloud或者單獨模式下,在單獨模式下這是唯一的方式。

1. 軟件版本

  Solr版本 8.8

  環境:

ip

主機名

角色

192.168.1.105

node1

zookeeper、solr、kdc、kadmin、kclient

192.168.1.109

node2

zookeeper、solr、kclient

192.168.1.103

node3

zookeeper、solr、kclient

  kdc、kadmin為kerberos的服務器節點,kclient為kerberos的客戶端節點

2. solr集成kerberos

2.1. 添加solr用戶

  在kdc中為solr添加主體並生成用於驗證HTTP請求的keytab文件,為每個要運行solr的主機創建一個keytab文件,並將主體名稱與主機一起使用:

root@kdc:/# kadmin.local
kadmin.local: addprinc -randkey HTTP/<hostname>@EXAMPLE.COM
kadmin.local: ktadd -k /tmp/solr.keytab HTTP/<hostname>@EXAMPLE.COM
kadmin.local: quit

  注:

    addprinc -randkey HTTP/\${HOST1}@EXAMPLE.COM,將${HOST1}替換為實際的主機名。

    上述操作需要每個solr節點都重復一遍,為每台solr節點創建kerberos HTTP用戶主體,並生成/tmp/solr.keytab文件,最后復制到solr節點的/keytabs/solr.keytab路徑。

  如上,solr節點分布在三台機器上,則需要執行如下命令添加:

root@kdc:/# kadmin.local
kadmin.local: addprinc -randkey HTTP/node1@EXAMPLE.COM
kadmin.local: ktadd -k /tmp/node1.keytab HTTP/node1@EXAMPLE.COM

kadmin.local: addprinc -randkey HTTP/node2@EXAMPLE.COM
kadmin.local: ktadd -k /tmp/node2.keytab HTTP/node2@EXAMPLE.COM

kadmin.local: addprinc -randkey HTTP/node3@EXAMPLE.COM
kadmin.local: ktadd -k /tmp/node3.keytab HTTP/node3@EXAMPLE.COM

  需要把node1.keytab、node2.keytab,node3.keytab分別放置在各自節點的/keytabs/路徑下,並重命名為solr.keytab

2.2. zookeeper配置(如果已配置kerberos則跳過)

  zookeeper管理solrcloud集群中的節點通信,它必須要與集群各節點中認證。配置要求為zookeeper設置服務principal,定義JAAS配置文件。

  第一步是在zookeeper的conf目錄創建java.env文件,並且添加如下內容:

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

  在kdc為zookeeper創建用戶主體並生成keytab文件,如下:

[root@node1 conf]# kadmin.local
kadmin.local:  addprinc -randkey zookeeper/node1@EXAMPLE.COM kadmin.local: addprinc -randkey zookeeper/node2@EXAMPLE.COM kadmin.local: addprinc -randkey zookeeper/node3@EXAMPLE.COM kadmin.local: ktadd -k /keytabs/zoo105.keytab zookeeper/node1@EXAMPLE.COM kadmin.local: ktadd -k /keytabs/zoo109.keytab zookeeper/node2@EXAMPLE.COM kadmin.local: ktadd -k /keytabs/zoo103.keytab zookeeper/node3@EXAMPLE.COM

  把生成的zoo105.keytab、zoo109.keytab、zoo103.keytab分別放置105、109、103服務器的同一路徑/keytabs下,並重名為zoo.keytab

  JAAS配置文件應該包含下面的參數,確保改變principal和keytab的路徑。jaas-client.conf配置內容如下:

Server {
 com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/keytabs/zkhost1.keytab"
  storeKey=true
  doNotPrompt=true
  useTicketCache=false
  debug=true
  principal="zookeeper/host1@EXAMPLE.COM";
};

  最后,在zookeeper配置文件zoo.cfg添加如下內容:

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

  啟動zookeeper,如下:

bin/zkServer.sh start

2.3. 創建security.json

  在solrcloud模式中,設置solr通過上傳security.json到zookeeper來使用kerberos插件

server/scripts/cloud-scripts/zkcli.sh -zkhost node1:2181,node2:2181,node3:2181 -cmd put /solr/security.json '{"authentication":{"class":"org.apache.solr.security.KerberosPlugin"}}'

  如果你使用solr的standalone模式,需要創建security.json文件,然后放置在$SOLR_HOME目錄下方。

  注:

    /solr/security.json這里的/solr為solr在zookeeper的chroot路徑,放錯路徑,solr的kerberos認證不生效。可以查看2.6節點的solr啟動命令會帶有

bin/solr -c -z node1:2181,node2:2181,node3:2181/solr

  zookeeper后面會帶有/solr路徑,即是solr在zookeeper的根路徑。

2.4. 創建jaas文件

  JAAS配置文件定義認證屬性使用,例如服務principal和keytab路徑。在下面的例子中,我們創建JAAS配置文件/home/foo/jaas-client.conf。當我們啟動solr的時候,我們將會使用該名字和路徑。確保使用正確principal和keytab文件路徑。

Client {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/keytabs/solr.keytab"
    storeKey=true
    useTicketCache=true
    debug=true
    principal="HTTP/${hostname}@EXAMPLE.COM";
};

  注:

  每個solr節點都需要執行這一步,${hostname}為對應solr節點的主機名。principal="HTTP/${hostname}@EXAMPLE.COM"后面需要加分號,不然會報錯

2.5. 在solr.in.sh中添加以下內容

  當啟動solr的時候,需要配置solr的start命令中屬性參數,示例如下:

SOLR_AUTH_TYPE="kerberos"
SOLR_JAAS_FILE=/home/redpeak/app/ranger-solr-8.3.0-cloud/ranger_audit_server/conf/jaas-client.conf
SOLR_HOST=`hostname -f`
SOLR_KERB_PRINCIPAL=HTTP/node1@EXAMPLE.COM
SOLR_KERB_KEYTAB=/keytabs/solr.keytab

SOLR_AUTHENTICATION_OPTS=" -Dsun.security.krb5.debug=true -Dsolr.authentication.type=kerberos -Djava.security.auth.login.config=${SOLR_JAAS_FILE} -Dsolr.kerberos.cookie.domain=${SOLR_HOST} -Dsolr.kerberos.name.rules=DEFAULT -Dsolr.kerberos.cookie.portaware=true -Dsolr.kerberos.principal=${SOLR_KERB_PRINCIPAL} -Dsolr.kerberos.keytab=${SOLR_KERB_KEYTAB}"

  注:

  SOLR_KERB_PRINCIPAL=HTTP/node1@EXAMPLE.COM中的node1,每台節點不一樣,需要切換。

2.6. 啟動solr

bin/solr -c -z server1:2181,server2:2181,server3:2181/solr

2.7. 測試配置

  第一步執行如下命令:

kinit user@EXAMPLE.COM

  第二步執行如下命令,curl,會得到成功的反應:

curl --negotiate -u : "http://node1:6083/solr/"

3. solrJ的認證

3.1. 基礎配置

   在solrJ應用中使用kerberos認證,需要在創建solr客戶端之前執行下面兩步:

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

  你需要為JAAS客戶端配置jaas-client.conf指定kerberos服務principal和keytab,如下:

SolrJClient {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/keytabs/foo.keytab"
    storeKey=true
    useTicketCache=true
    debug=true
    principal="foo@EXAMPLE.COM";
};

  注:  

    principal="foo@EXAMPLE.COM"后面需要加分號。

3.2. solr.5.5版本demo

3.2.1. pom.xml配置 

        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-solrj</artifactId>
            <version>5.5.4</version>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>

  注意:

    低版本的solrJ需要配置slf4j日志jar包,否則會莫名報錯,如下:

    org.apache.solr.common.SolrException: java.util.concurrent.TimeoutException: Could not connect to ZooKeeper host1:2181,host2:2181,host3:2181/infra-solr within 10000 ms

3.2.2. java代碼 

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.*;
import org.apache.solr.client.solrj.response.QueryResponse;

public class solrTest {
    public static void main(String[] args) {
        try {
            //System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
            System.setProperty("java.security.krb5.conf", "D:\\krb5.conf");

            System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
            System.setProperty("sun.security.krb5.debug", "true");

            //System.setProperty("java.security.auth.login.config", "/home/redpeak/ranger_solr_jaas_test.conf");
            System.setProperty("java.security.auth.login.config", "D:\\ranger_solr_jaas_test.conf");


            Krb5HttpClientConfigurer krb5 = new Krb5HttpClientConfigurer();
            HttpClientUtil.setConfigurer(krb5);
            System.out.println(HttpClientUtil.getConfigurer().toString());

            /**
             * the first method:  用於集群solrCloud模式,通過zookeeper訪問,
             * 注意:當solr開啟kerberos后,不能直接通過ip訪問zookeeper,會報錯401沒有認證,需要改為hostname,並在hosts里面配置ip和hostname映射關系
             */
            //CloudSolrClient solrCloudClient = new CloudSolrClient("192.168.1.165:2181,192.168.1.166:2181,192.168.1.167:2181/infra-solr");
            CloudSolrClient solrCloudClient = new CloudSolrClient("host1:2181,host2:2181,host3:2181/infra-solr");
            solrCloudClient.setDefaultCollection("ranger_audits");
            solrCloudClient.setZkClientTimeout(10000);
            solrCloudClient.setZkClientTimeout(20000);
            solrCloudClient.connect();
            SolrQuery params = new SolrQuery("*:*");
            QueryResponse qr = solrCloudClient.query(params);
            System.out.println(qr.getResults());

            /**
             * the second method:  用於standalone模式或者集群solrCloud模式,通過http訪問
             * 注意:當solr開啟kerberos后,不能直接通過ip訪問web ui,會報錯zookeeper連接超時,需要改為hostname,並在hosts里面配置ip和hostname映射關系
             */
            //String solrURL = "http://192.168.1.165:8886/solr/ranger_audits";
            String solrURL = "http://host1:8886/solr/ranger_audits";
            HttpSolrClient solrClient = new HttpSolrClient(solrURL);
            solrClient.setAllowCompression(true);
            solrClient.setConnectionTimeout(1000);
            solrClient.setRequestWriter(new BinaryRequestWriter());
            SolrQuery params2 = new SolrQuery("*:*");
            QueryResponse qr2 = solrClient.query(params2);
            System.out.println(qr2.getResults());

        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

  注意:

    無論是CloudSolrClient還是HttpSolrClient,當solr開啟kerberos后,不能直接通過ip訪問,只能通過hostname訪問,並在hosts里面配置ip和hostname映射關系。

3.3. solr.7.7.0版本demo

3.3.1. pom.xml配置 

        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-solrj</artifactId>
            <version>7.7.0</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>

3.3.2. java代碼 

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.*;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.params.ModifiableSolrParams;

public class solrTest2 {
    public static void main(String[] args) {
        try {
            //System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
            System.setProperty("java.security.krb5.conf", "D:\\krb5.conf");
            
            System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
            System.setProperty("sun.security.krb5.debug", "true");
            
            //System.setProperty("java.security.auth.login.config", "/home/redpeak/ranger_solr_jaas_test.conf");
            System.setProperty("java.security.auth.login.config", "D:\\ranger_solr_jaas_test.conf");

            /**
             * 用於standalone模式或者集群solrCloud模式,通過http訪問
             * 注意:當solr開啟kerberos后,不能直接通過ip訪問web ui,會報錯401沒有認證,需要改為hostname,並在hosts里面配置ip和hostname映射關系
             */
            //HttpSolrClient.Builder solrClientBuilder = new HttpSolrClient.Builder("http://192.168.1.165:8886/solr/ranger_audits");
            HttpSolrClient.Builder solrClientBuilder = new HttpSolrClient.Builder("http://host1:8886/solr/ranger_audits");
            SolrHttpClientBuilder solrHttpClientBuilder = new Krb5HttpClientBuilder().getHttpClientBuilder(java.util.Optional.empty());
            HttpClientUtil.setHttpClientBuilder(solrHttpClientBuilder);

            ModifiableSolrParams params = new ModifiableSolrParams();
            params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false);

            CloseableHttpClient httpClient = HttpClientUtil.createClient(params);
            SolrClient client = solrClientBuilder.withHttpClient(httpClient).build();

            SolrQuery params2 = new SolrQuery("*:*");
            QueryResponse qr = client.query(params2);

            System.out.println(qr.getResults());
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

  注意:

    當solr開啟kerberos后,不能直接通過ip訪問,只能通過hostname訪問,並在hosts里面配置ip和hostname映射關系。

4. 參考資料

https://solr.apache.org/guide/8_8/kerberos-authentication-plugin.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM