以Kafka 2.3.0版本为例,实现通过配置SASL SCRAM + ACL来实现动态增减用户.以下是具体步骤
创建普通用户,用于客户端读写测试
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=user],SCRAM-SHA-512=[password=user]' --entity-type users --entity-name user
创建admin用户,用于Kafka broker间内部通讯
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --alter --add-config 'SCRAM-SHA-256=[password=admin],SCRAM-SHA-512=[password=admin]' --entity-type users --entity-name admin
Kafka只支持强哈希函数SHA-256和SHA-512,如果没有指定迭代,则使用默认的迭代计数4096。创建一个随机salt,并在ZooKeeper中存储由salt、iteration、StoredKey和ServerKey组成的SCRAM标识.如果ZooKeeper安全性受到威胁,强哈希函数结合强密码和高迭代计数可以防止暴力攻击.
使用命令查看一下创建好的用户的信息,以admin为例,里面包含了admin用户加密算法SCRAM-SHA-256以及SCRAM-SHA-512对应的盐值(salt)、ServerKey和StoreKey等
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --describe --entity-type users --entity-name admin
Configs for user-principal 'admin' are SCRAM-SHA-512=salt=MTZqMmh1Y3V5Y3c4ZmF1YzVnajk1NjZoeDc=,stored_key=gk2qTgocH711dwzzC5IK4Bp6eI115S1lFA2nK+0LaYiLzB7dpdppaA09YZVcOo1GMTLOdaJ4uIv+74E4pdvQJQ==,server_key=pUlkM3ESnlKO+TAdntOJCD/lw3vfgcLcRBYmLrKVsE7Z7pAF3R01iIEJgrwJ40Hp6vO/17JfyJsN60SF/jld0Q==,iterations=4096,SCRAM-SHA-256=salt=ZmxtN3Jzcmg4M3p3ZnRvdXR0MHc1ZXN1aw==,stored_key=SM2j1/nCyLYud4iTQ97WHLAkQh82mY3DCCMSFYRcb90=,server_key=J98vkGXa8mZ2k5f5a1W1RB9MSgiJDgLPFAj7EL9h2dY=,iterations=4096
配置broker,为每个broker物理节点创建一个对应的jaas文件(内容相同),命名为kafka_server_jaas.conf.以下是kafka_server_jaas.conf文件的内容
1.注意末尾的两个分号
2.另外不要任何空白键
- 这里配置admin用户用于broker间的内部通讯
KafkaServer {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="admin";
};
修改broker端的server.properties,增加 SASL 端口 and SASL 机制等相关配置
启用ACL
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
设置本例中admin为超级用户
super.users=User:admin
启用SCRAM机制,采用SCRAM-SHA-512算法
sasl.enabled.mechanisms=SCRAM-SHA-512
为broker间通讯开启SCRAM机制,采用SCRAM-SHA-512算法
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-512
broker间通讯使用PLAINTEXT,本例中不演示SSL配置
security.inter.broker.protocol=SASL_PLAINTEXT
配置listeners使用SASL_PLAINTEXT
listeners=SASL_PLAINTEXT://172.0.0.1:9092
配置advertised.listeners
advertised.listeners=SASL_PLAINTEXT://172.0.0.1:9092
除了上面提到的,还有一个重要的参数allow.everyone.if.no.acl.found,故这个参数默认是false.
false:对于Kafka集群而言,如果没有ResourcePatterns匹配特定的资源R,那么R就没有关联的acl,因此除了超级用户之外,没有人可以访问R,相当于白名单
true:如果资源找不到acl配置,默认是可以访问该资源,可以理解为黑名单
每台物理节点的kafka配置完成后。分别启动各节点的broker实例.
注意引入jaas文件的方式,将-Djava.security.auth.login.config作为KAKFA_OPTS环境变量的方式进行设置.参考如下脚本
!/bin/bash
export JMX_PORT=19998
export JAVA_HOME=/usr/java/jdk1.8.0_71/
export KAFKA_HOME=/usr/local/datacenter/kafka_2.11-2.3.0/
export PATH=JAVA_HOME/bin
export KAFKA_HEAP_OPTS="-Xmx6G -Xms6G -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:G1HeapRegionSize=16M -XX:MinMetaspaceFreeRatio=50 -XX:MaxMetaspaceFreeRatio=85"
export KAFKA_OPTS=-Djava.security.auth.login.config=/usr/local/datacenter/kafka_2.11-2.3.0/config/kafka_server_jaas.conf
sh KAFKA_HOME/config/server.properties
测试生产者
使用console-producer脚本来发送消息, 消息发送失败了,原因是没有指定合法的认证用户,
./kafka-console-producer.sh --topic test --broker-list localhost:9092
[2019-07-31 23:04:47,568] WARN [Producer clientId=console-producer] Bootstrap broker localhost:9092 (id: -1 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
[2019-07-31 23:04:47,746] WARN [Producer clientId=console-producer] Bootstrap broker localhost:9092 (id: -1 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
现在指定用户user发送生产消息——为此我需要创建一个名为producer.conf的配置文件给生产值程序使用,如下
vi producer.conf
security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="user" password="user";
./kafka-console-producer.sh --topic test --broker-list localhost:9092 --producer.config producer.conf
异常发生变化了,这是因为用户user没有对test topic的写权限
[2019-07-31 23:02:56,516] WARN [Producer clientId=console-producer] Error while fetching metadata with correlation id 3 : {test=TOPIC_AUTHORIZATION_FAILED} (org.apache.kafka.clients.NetworkClient)
[2019-07-31 23:02:56,517] ERROR [Producer clientId=console-producer] Topic authorization failed for topics [test] (org.apache.kafka.clients.Metadata)
[2019-07-31 23:02:56,518] ERROR Error when sending message to topic test with key: null, value: 0 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)
org.apache.kafka.common.errors.TopicAuthorizationException: Not authorized to access topics: [test]
给用户user增加该topic的写权限后,生产消息执行成功:
./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer --authorizer-properties zookeeper.connect=localhost:2181/kafka --add --allow-principal User:user --operation Write --topic test
./kafka-console-producer.sh --topic test --broker-list localhost:9092 --producer.config producer.conf
测试消费者
下面是配置consumer程序,和上面测试producer一样,需要先为user用户增加对topic的读权限,然后在消费者程序指定配置,因为使用同一用户直接指定
producer.conf即可
./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer --authorizer-properties zookeeper.connect=localhost:2181/kafka --add --allow-principal User:user --operation Read --topic test
./kafka-console-consumer.sh --topic test --bootstrap-server localhost:9092 --group test --consumer.config producer.conf
意想不到的是,没有执行成功,报错提示用户user没有访问消费组test的权限,
[2019-07-31 23:23:27,315] ERROR Error processing message, terminating consumer process: (kafka.tools.ConsoleConsumer$)
org.apache.kafka.common.errors.GroupAuthorizationException: Not authorized to access group: test
增加用户user访问消费组test的权限,重新执行后成功
./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer --authorizer-properties zookeeper.connect=localhost:2181/kafka --add --allow-principal User:user --operation Read --topic test --group test
测试使用kafka-topics.sh
提示:使用 kafka-topics.sh管理topic等操作是也是要指定任务用户的.
./kafka-topics.sh --list --bootstrap-server localhost:9092 --command-config producer.conf
动态增删用户
删除用户的SCRAM证书
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --alter --delete-config 'SCRAM-SHA-512' --entity-type users --entity-name user
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --alter --delete-config 'SCRAM-SHA-256' --entity-type users --entity-name user
查看user的用户的信息
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --describe --entity-type users --entity-name user
查看zookeeper中的元数据,关于user的用户的信息也同时被清空
[zk: localhost:2181/kafka(CONNECTED) 0] get /kafka/config/users/user
{"version":1,"config":{}}
通过创建user用户,指定认证用户的配置后,相关生产消费的程序又可正常使用
bin/kafka-configs.sh --zookeeper localhost:2181/kafka --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=user],SCRAM-SHA-512=[password=user]' --entity-type users --entity-name user
至此可以动态增加用户的权限认证方式就大功告成了