kafka身份认证与访问控制

5,334 阅读3分钟

1. kafka安全设置分类

1.1 消息加密SSL

将kafka消息使用SSL加密,类似于http到https的升级。可以避免通过网卡窃取到消息内容。但是SSL会导致kafka无法使用零拷贝特性,官方说法是降低性能9%左右。

1.2 访问认证SASL

生产者和消费者访问kafka需要用户名和密码认证。分为PLAIN、SCRAM、GSSAPI、OAUTHBEARER等,PLAIN的缺点是kafka集群启动后不能动态修改用户,修改需要重启,不大适合生产环境,SCRAM克服了这一缺点,GSSAPI则是使用额外的Kerberos组件,OAUTHBEARER主要支持Oauth场景。

1.3 权限控制ACL

为了避免某一服务误操作影响所有topic,可以对每个user添加acl,只能对指定的topic进行读或者写。
身份认证与访问控制主要涉及的是2和3。

2. kafka集群添加SCRAM认证

kafka集群的SCRAM认证并不会影响到zookeeper集群。 不论是裸机环境还是容器中的kafka集群,改造主要分为三部分。

2.1 添加scram_jaas文件

文件内容为加密方式,使用超级管理员用户和密码。因为其他用户还没有设置权限,默认是没有任何权限,所以无法读写任何topic。

KafkaServer {
  org.apache.kafka.common.security.scram.ScramLoginModule required
  username="admin"
  password="xxxxx";
};

注意,这里配置的admin用户具有所有权限,不需要后面继续配置,其他用户如果不配置权限,默认没有任何权限,执行任何写入或者访问操作都会报错,所以我们在下面执行配置操作的时候都是用这个admin用户。
另外,scram使用的是org.apache.kafka.common.security.scram.ScramLoginModule,还有一种org.apache.kafka.common.security.plain.PlainLoginModule对应的就是普通的SASL加密,不能动态修改用户的那个。

2.2 修改kafka启动脚本

目的是启动时加载2.1添加的文件。
修改kafka-server-start.sh脚本,将最后一行替换为

exec $base_dir/kafka-run-class.sh $EXTRA_ARGS -Djava.security.auth.login.config=$base_dir/../config/kafka_server_scram_jaas.conf  kafka.Kafka "$@"

其中的kafka_server_scram_jaas.conf文件就是上面的文件,注意路径要写对,换成你自己的文件路径。这是一种方法。
还可以设置环境变量

KAFKA_PLAIN_PARAMS="-Djava.security.auth.login.config=/kafka_2.13-2.6.0/config/kafka_server_scram_jaas.conf"
KAFKA_OPTS="$KAFKA_PLAIN_PARAMS $KAFKA_OPTS"

这种方法在制作docker镜像或者使用k8s部署kafka的时候比较方便,直接在Dockerfile文件添加

ENV KAFKA_PLAIN_PARAMS="-Djava.security.auth.login.config=/kafka_2.13-2.6.0/config/kafka_server_scram_jaas.conf"
ENV KAFKA_OPTS="$KAFKA_PLAIN_PARAMS $KAFKA_OPTS"

2.3 修改配置文件server.properties

加上scram相关设置 主要是listeners需要把

listeners=PLAINTEXT://localhost:9092

修改为

listeners=SASL_PLAINTEXT://10.95.123.66:9092

并在文件末尾添加

security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256
sasl.enabled.mechanisms=SCRAM-SHA-256
allow.everyone.if.no.acl.found=false
super.users=User:admin
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer

以上三步修改好,直接启动kafka集群。

3. 权限设置

3.1 添加用户

分别添加管理员用户和普通用户,信息写入zookeeper

./kafka-configs.sh --zookeeper ip:port --alter --add-config 'SCRAM-SHA-256=[password=xxx],SCRAM-SHA-512=[password=xxx]' --entity-type users --entity-name xxx
./kafka-configs.sh --zookeeper ip:port --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=xxx],SCRAM-SHA-512=[password=xxx]' --entity-type users --entity-name xxx

用户信息存在zookeeper,这就是SCRAM能动态修改用户的原因。

3.2 测试访问

同上面一样创建kafka_client_scram_jaas.conf文件,只不过这个文件是给客户端访问kafka使用的,里面填上用户名名和密码。与kafka_server_scram_jaas.conf他们的主要区别是```

KafkaServer和KafkaClient两个词。
KafkaClient {
  org.apache.kafka.common.security.scram.ScramLoginModule required
  username="xxxxx"
  password="xxxxx";
};

分别修改kafka-console-producer.shkafka-console-consumer.sh文件的最后一行

exec $(dirname $0)/kafka-run-class.sh -Djava.security.auth.login.config=/usr/local/kafka_2.13-2.6.0/bin/kafka_client_scram_jaas.conf kafka.tools.ConsoleProducer "$@"
exec $(dirname $0)/kafka-run-class.sh -Djava.security.auth.login.config=/usr/local/kafka_2.13-2.6.0/bin/kafka_client_scram_jaas.conf kafka.tools.ConsoleConsumer "$@"

创建client.properties文件:

security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-256

分别执行

./kafka-console-producer.sh --broker-list 10.95.123.66:9092 --topic test --producer.config ./client.properties
./kafka-console-consumer.sh  --bootstrap-server 10.95.123.66:9092  --topic test --from-beginning --consumer.config ./client.properties

就可以在producer侧输入,从consumer侧看到输出。

3.3 acl设置

没有配置acl权限的用户默认是不能访问任何topic的(admin用户可以访问所有),下面是赋予读写权限的操作

./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer --authorizer-properties zookeeper.connect=ip:port --add --allow-principal User:xxx --operation Read --topic xxx 
./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer --authorizer-properties zookeeper.connect=ip:port --add --allow-principal User:xxx --operation Write --topic xxx

查看权限设置列表

./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer --authorizer-properties zookeeper.connect=ip:port --list