Kerberos原理安装集成kafka例子

目录

Kerbeos简介

Kerbeos认证流程

Kerberos安装步骤

kerberos简单操作

Kafka集成Kerberos例子

本地环境java客户端消费测试代码

错误记录


 

Kerbeos简介

       Kerberos可以将认证的密钥在集群部署时事先放到可靠的节点上。集群运行时,集群内的节点使用密钥得到认证,认证通过后的节点才能提供服务。企图冒充的节点由于没有事先得到的密钥信息,无法与集群内部的节点通信。这样就防止了恶意地使用或篡改Hadoop集群的问题,确保了Hadoop集群的可靠性、安全性。

名词解释

  • AS(Authentication Server): 认证服务器
  • KDC(Key Distribution Center): 密钥分发中心
  • TGT(Ticket Granting Ticket): 票据授权票据,票据的票据
  • TGS(Ticket Granting Server):票据授权服务器
  • SS(Service Server): 特定服务提供端
  • Principal: 被认证的个体
  • Ticket: 票据, 客户端用来证明身份真实性。包含: 用户名,IP,时间戳,有效期,会话秘钥。 
     

Kerbeos认证流程

一、客户端认证:

1、client发送请求AS,AS验证DB是否存在该用户,存在即返回两个消息A和B
消息A:Client和TGS通信的会话秘钥,该消息通过用户秘钥进行加密
消息B:票据授权票据(TGT),内容包含消息A中Client/TGS的会话秘钥、用户ID、用户网址、TGT有效期,该消息通过TGS密码进行加密

注意:用户不向AS发送“用户密钥”(user's secret key),也不发送密码,AS能够从本地数据库查到申请用户的密码,并通过转换得到用户秘钥

2、client收到两个返回消息,首先尝试用自己秘钥解密消息A,如果用户输入的密码与AS数据库中的密码不符,则不能成功解密消息A。
正确即得到Client/TGS的会话秘钥。

注意:Client不能解密消息B,因为消息B是用TGS秘钥加密的,有了Client/TGS会话秘钥,Client就足以TGS进行认证了。

二、服务授权:

1、Client需要申请特定服务时,向TGS发送两个消息C和D
消息C:消息B的内容和想获取的服务ID(不是用户ID)
消息D:认证符Authenticator(包括:用户ID,时间戳),通过Client/TGS会话密钥进行加密。

2、TGS收到消息C和D,首先检查KDC数据库中是否存在所需服务,然后用自己的秘钥解密消息B(TGT),从而得到Client/TGS会话秘钥,
TGS再用这个秘钥解密消息D得到用户ID和时间戳,并对TGT和Authenticator进行验证,通过后返回两条消息E和F
消息E:Client-server票据(包括Client/SS的会话密钥,用户ID,用户网址,有效期),通过服务器秘钥进行加密
消息F:Client/SS会话密钥,用在将来Client和SS通信,通过Client/TGS进行加密

3、Client收到消息E和F后,用Client/TGS会话秘钥解密消息F,得到Client/SS会话秘钥

注意:Client不能解密消息E,因为E是用“服务器密钥”(service's secret key)加密的

三、服务请求:

1、获得Client/SS会话密钥之后, Client就能够使用服务器提供的服务了。Client向指定服务器SS发出2条消息G和H
消息G:即上一步消息E,通过服务器秘钥加密
消息H:即新的Authenticator(包括用户ID,时间戳),通过Client/SS会话秘钥进行加密

2、SS用自己的秘钥解密消息G从而得到Client/SS会话秘钥,再用这个秘钥解密消息H得到Authenticator,对Ticket和
Authenticator进行验证,通过即返回消息I(确认身份成功,乐于提供服务)
消息I:新时间戳(Client发送的时间戳+1),通过Client/SS会话秘钥加密

3、Client通过Client/SS解密,得到新时间戳并验证,通过则信赖服务器,并向服务器发送服务请求

4、服务器向客户端提供相应的服务


 

Kerberos安装步骤

1、安装Kerberos相关软件

yum install krb5-server krb5-libs krb5-workstation -y

2、配置kdc.conf

vim /var/kerberos/krb5kdc/kdc.conf


内容如下:

[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88

[realms]
HADOOP.COM = {
#master_key_type = aes256-cts
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
max_renewable_life = 7d
supported_enctypes = aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
 }
  • HADOOP.COM:是设定的realms。名字随意。Kerberos可以支持多个realms,一般全用大写
  • masterkeytype,supported_enctypes默认使用aes256-cts。由于,JAVA使用aes256-cts验证方式需要安装额外的jar包,这里暂不使用
  • acl_file:标注了admin的用户权限。
  • admin_keytab:KDC进行校验的keytab
  • supported_enctypes:支持的校验方式。注意把aes256-cts去掉

3、配置krb5.conf

vim /etc/krb5.conf

内容如下:

# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = HADOOP.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 clockskew = 120
 udp_preference_limit = 1
[realms]
 HADOOP.COM = {
  kdc = es1    //改为服务器主机名
  admin_server = es1   //改为服务器主机名
 }

[domain_realm]
 .hadoop.com = HADOOP.COM
 hadoop.com = HADOOP.COM

4、初始化kerberos database

kdb5_util create -s -r HADOOP.COM

5、修改database administrator的ACL权限

vim /var/kerberos/krb5kdc/kadm5.acl

#修改如下
*/[email protected]  *

6、启动kerberos daemons

systemctl start kadmin krb5kdc
systemctl enable kadmin krb5kdc


 

kerberos简单操作

首先以超管身份进入kadmin

kadmin.local

查看用户

listprincs

新增用户kafka/es1

addprinc kafka/es1

修改testUser密码

change_password kafka/es1

删除testUser

delete_principal kafka/es1

使用问号查看所有命令用法

?

退出kadmin.local

exit


 

Kafka集成Kerberos例子

1、生成用户keytab(该文件后续kafka配置和客户端认证需用到)

kadmin.local -q "xst  -k /var/kerberos/krb5kdc/kadm5.keytab  kafka/[email protected]"

注意:生成keytab后,密码被修改了,无法再用之前密码登陆

不改变密码的方法:

       kadmin.local

       xst -k kadmin.keytab -norandkey kafka/[email protected]

2、在kafka安装目录下config创建kafka-jaas.conf

KafkaServer {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
keyTab="/var/kerberos/krb5kdc/kadm5.keytab"
principal="kafka/[email protected]";
};

KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=true
keyTab="/var/kerberos/krb5kdc/kadm5.keytab"
principal="kafka/[email protected]";
};

3、在config/server.properties添加如下配置

advertised.listeners=SASL_PLAINTEXT://es1:9092
listeners=SASL_PLAINTEXT://es1:9092
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanisms=GSSAPI
sasl.kerberos.service.name=kafka

4、在bin/kafka-run-class.sh脚本添加kafka jvm参数(下划线部分内容)

#jvm performance options
if [ -z "$KAFKAJVMPERFORMANCEOPTS" ]; then KAFKAJVMPERFORMANCEOPTS="-server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -Djava.awt.headless=true -Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/home/xingtongping/kafka_2.12-2.2.0/config/kafka-jaas.conf" fi

5、配置config/producer.properties,kafka生产者kerberos配置

security.protocol = SASL_PLAINTEXT
sasl.mechanism = GSSAPI
sasl.kerberos.service.name =kafka

6、配置config/consumer.properties,kafka消费者kerberos配置

security.protocol = SASL_PLAINTEXT
sasl.mechanism = GSSAPI
sasl.kerberos.service.name=kafka

 

linux测试命令

启动kafka服务

bin/kafka-server-start.sh config/server.properties

生产者

bin/kafka-console-producer.sh --broker-list es1:9092 --topic test  --producer.config config/producer.properties

消费者

bin/kafka-console-consumer.sh --bootstrap-server es1:9092 --topic test  --consumer.config config/consumer.properties

本地环境java客户端消费测试代码

注意:
1、把krb5.conf和kafka-jaas.conf下载到本地,并且修改kafka-jaas.conf文件的keytab路径:改为本地keytab路径
2、使用域名记得修改hosts文件,添加内容:172.16.110.173 es1

public class Consumer {
    public static void main(String[] args) throws IOException {

     System.setProperty("java.security.krb5.conf","C:/Users/Administrator/Downloads/krb5.conf");              //认证代码
     System.setProperty("java.security.auth.login.config","C:/Users/Administrator/Downloads/kafka-jaas.conf");//认证代码
     Properties props = new Properties();
      //集群地址,多个地址用","分隔
     props.put("bootstrap.servers", "es1:9092");           
     props.put("sasl.kerberos.service.name", "kafka");     //认证代码
     props.put("sasl.mechanism", "GSSAPI");                //认证代码
     props.put("security.protocol", "SASL_PLAINTEXT");     //认证代码
     props.put("group.id", "1");
     props.put("enable.auto.commit", "true");
     props.put("auto.commit.interval.ms", "1000");
     props.put("session.timeout.ms", "30000");
     props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
     props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

     //创建消费者
     KafkaConsumer consumer = new KafkaConsumer(props);
     // 订阅topic,可以为多个用,隔开,此处订阅了"test"这个主题
     consumer.subscribe(Arrays.asList("test"));
     //持续监听
     while(true){
        //poll频率
        ConsumerRecords consumerRecords = consumer.poll(100);
        for(ConsumerRecord consumerRecord : consumerRecords){
            System.out.println("在test中读到:" + consumerRecord.value());
        }
    }
 }
}


 

错误记录

问题一:

我在用linux命令启动消费者的时候出现,如图所示

Kerberos原理安装集成kafka例子_第1张图片

解决办法: 这个问题是因为我没有在kafka-jaas.conf中添加KafkaClient配置,所以在kafka-jaas.conf添加配置就解决了 #内容如下 KafkaClient { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true useTicketCache=true keyTab="/var/kerberos/krb5kdc/kadm5.keytab" principal="kafka/[email protected]"; };

问题二:

解决了问题一后,我继续用linux命令启动消费者,结果出现如图所示错误,启动命令如下

Kerberos原理安装集成kafka例子_第2张图片

bin/kafka-console-consumer.sh --bootstrap-server 172.16.110.173:9092 --topic test  --consumer.config config/consumer.properties

解决办法: 看错误信息可看出,提示说在kerberos数据库中找不到服务器,困扰了很久,后来我把启动命令改为如下即成功了,即把ip改为域名,
可能服务器向kerberos注册时候使用了es1,我猜想跟krb5.conf文件配置中有关,改文件且需初始化数据库(猜想) 使用下面命令启动: bin/kafka-console-consumer.sh --bootstrap-server es1:9092 --topic test --consumer.config config/consumer.properties

问题三:

启动生产者或者消费者时候没有认证通过的时候,貌似kafka服务端就会一直出现图中信息,如kafka集成了kerberos,但是java客户端仍然用原来没有认证的代码访问。

问题四:

本地使用java代码消费的时候出现,如图所示

Kerberos原理安装集成kafka例子_第3张图片

解决办法: 把下载的kafka-jaas.conf中keytab路径改为本地路径即可

问题五:

本地使用java代码消费的时候出现,如图所示

Kerberos原理安装集成kafka例子_第4张图片

解决办法: 把错误信息百度翻译了一波,Clock skew too great,时钟偏差太大,于是我看了看服务器时间和本地时间,相差了5分钟,我把本地事件调整下,最终完成了。

问题六

安装完kerberos,使用kinit登陆时出现报错

 

解决办法:

检查/etc/krb5.conf文件中realms配置主机是否正确
HADOOP.COM = {
    kdc = es1            
    admin_server = es1   
}


 

重装了一遍

后来为了验证文章正确,又用一台服务器重新装了一遍,发现了一些问题。

注意:

1、创建kerberos的用户时候,命名格式感觉要规范

服务名/主机名
如服务名为kafka,主机名为es1
即命名为kafka/es1

在server.properties、consumer.properties、producer.properties等文件都要用到服务名,即kafka

2、别忘了修改/etc/hosts文件做域名映射哦

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.17.196.210  xtp

3、如果之前已经初始化过一次数据库,后来需要修改krb5.conf内容,如服务器名字变了,在运行时遇到错误说server不在kerberos的数据库中,这时候可能需要重新初始化这个realm,步骤如下:

1、删除krb5kdc目录下的principal开头的文件

命令:rm -rf /var/kerberos/krb5kdc/principal*

2、初始化kerberos database

命令:kdb5_util create -s -r HADOOP.COM

 

2019-05-29更新:

问题记录:

集群:spark01  、spark02 、spark03

搭建集群的时候,kafka-jaas.conf配置文件的kafkaServer我统一使用了kafka/spark01用户,结果搭建起来创建topic,查看topic都正常,但是生产者不能生产消息,消费者不能消费消息,出现了各种各样的错误。

生产者发送消息时:

后来在启动kafka的日志中发现不太一样,spark01的日志会全一点,包含很多group metadata等字眼的日志信息,spark02和spark03看起来正常启动了,但是缺少了这部分日志,我觉得集群有问题,我猜想是因为统一使用了kafka/spark01的用户问题,因为只有spark01节点启动日志完整,于是给各个节点使用不同的用户,如spark02使用kafka/spark02的配置,最终启动日志正常,生产者和消费者也正常


 

你可能感兴趣的:(kerberos,kafka安全,kafka+kerberos,kerberos原理,kerberos安装)