一、背景
在我們部署完kafka之後,雖然我們已經可以“肆意”的用kafka了,但是在一個大公司的實際生產環境中,kafka集羣往往十分龐大,每個使用者都應該只關心自己所負責的Topic,並且對其他人所使用的Topic沒有權限。這樣一來可以將資源隔離開來,二來可以防止誤操作。
在權限控制之前,我們必須要啓用的就是用戶認證,沒有用戶,自然沒有權限一說了。
二、kafka啓用kerberos認證
2.1 在KDC中添加kafka用戶,並生成keytab
新建kfaka用戶 | kadmin.local -q 'addprinc -randkey kafka/{hostname}@{REALM}' |
生成keytab | kadmin.local -q "ktadd -k /etc/security/keytabs/{keytabname}.keytab kafka/{hostname}@{REALM}" |
注意:
1、如果之前zookeeper沒有啓用kerberos,這裏也要啓用zookeeper的kerberos
2、如果之前在CM中啓用了kerberos,我們可以直接從CM中獲取keytab,但是注意keytab一定要保持最新的,否則認證不會通過,keytab的位置是:
/var/run/cloudera-scm-agent/process/****-kafka-KAFKA_BROKER/kafka.keytab
/var/run/cloudera-scm-agent/process/****-zookeeper-server/zookeeper.keytab
2.2 修改server.properties
//修改這一句 listeners=SASL_PLAINTEXT://host.name:port //新增以下 authorizer.class.name = kafka.security.auth.SimpleAclAuthorizer security.inter.broker.protocol=SASL_PLAINTEXT sasl.mechanism.inter.broker.protocol=GSSAPI sasl.enabled.mechanisms=GSSAPI sasl.kerberos.service.name=kafka super.users=User:kafka |
2.3 新建kafka_server.jaass
KafkaServer { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true serviceName="kafka" keyTab="/etc/keytab/kafka_122.keytab" //替換爲自己的keytab所在位置 principal="kafka/{hostname}@{REALM}";//替換爲自己的keytab所對應principle };
// Zookeeper client authentication,因爲卡夫卡使用過程中會和zookeeper進行交互 Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true serviceName="zookeeper" keyTab="/etc/keytab/kafka_122.keytab" //替換爲自己的keytab所在位置 principal="kafka/{hostname}@{REALM}";//替換爲自己的keytab所對應principle }; |
2.4 修改啓動腳本
export KAFKA_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/root/kafka/config/kafka_server.jaas" //剛纔的kafka_server.jaas位置 |
2.5重啓broker
bin/kafka-server-stop.sh bin/kafka-server-start.sh |
2.6 客戶端啓用kerberos
在broker啓用kerberos之後,如果我們後續需要在命令行界面進行操作,及consumer與producer操作,我們需要在這些客戶端也配置上kerberos
2.6.1新增kafka_client.jaas
KafkaClient { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true keyTab="/etc/keytab/kafka_122.keytab" serviceName="kafka" principal="kafka/{hostname}@{REALM}"; };
// Zookeeper client authentication Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true serviceName="zookeeper" keyTab="/etc/keytab/kafka_122.keytab" principal="kafka/{hostname}@{REALM}"; };
|
2.6.2配置生效
當前會話生效: export KAFKA_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/opt/kafka/config/kafka_client.jaas" |
配置到環境變量中 vim /etc/profile 增加 export KAFKA_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/opt/kafka/config/kafka_client.jaas" |
2.6.3若有用到consumer或者producer,在consumer.properties或producer.properties中增加
security.protocol=SASL_PLAINTEXT sasl.mechanism=GSSAPI sasl.kerberos.service.name=kafka |
三、kafka啓用acl(參考http://orchome.com/185)
Kafka認證管理CLI(和其他的CLI腳本)可以在bin目錄中找到。CLI腳本名是kafka-acls.sh。啓用之前,需要在server.properties裏添加這句:
allow.everyone.if.no.acl.found=false |
以下列出了所有腳本支持的選項:
選項 | 描述 | 默認 | 類型選擇 |
--add | 添加一個acl |
| Action |
--remove | 移除一個acl |
| Action |
--list | 列出acl |
| Action |
--authorizer | authorizer的完全限定類名 | kafka.security.auth.SimpleAclAuthorizer | Configuration |
--authorizer-properties | key=val,傳給authorizer進行初始化,例如:zookeeper.connect=localhost:2181 |
| Configuration |
--cluster | 指定集羣作爲資源。 |
| Resource |
--topic [topic-name] | 指定topic作爲資源。 |
| Resource |
--group [group-name] | 指定 consumer-group 作爲資源。 |
| Resource |
-allow-principal | 添加到允許訪問的ACL中,Principal是PrincipalType:name格式。 |
| Principal |
--deny-principal | 添加到拒絕訪問的ACL中,Principal是PrincipalType:name格式。 |
| Principal |
--allow-host | --allow-principal中的principal的IP地址允許訪問。 | 如果--allow-principal指定的默認值是*,則意味着指定“所有主機” | Host |
--deny-host | 允許或拒絕的操作。 | ALL | Operation |
--operation | --deny-principal中的principals的IP地址拒絕訪問。 | 如果 --deny-principal指定的默認值是 * 則意味着指定 "所有主機" | Host |
--producer | 爲producer角色添加/刪除acl。生成acl,允許在topic上WRITE, DESCRIBE和CREATE集羣。 |
| Convenience |
--consumer | 爲consumer role添加/刪除acl,生成acl,允許在topic上READ, DESCRIBE 和 consumer-group上READ。 |
| Convenience |
--force | 假設所有操作都是yes,規避提示 |
| Convenience |
常用命令舉例:因爲kafka的acl信息是存在zookeeper上的,所以需要提供zookeeper.connect參數,並且acl的存在與否與資源的存在與否無關。
最後的資源可以是topic,也可是cluster,也可以是consumer-group
給Bob和Alice從198.168.159.0(1)對test讀寫的權限 | bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --add --allow-principal User:Bob --allow-principal User:Alice --allow-host 198.168.159.0 --allow-host 198.168.159.1 --operation Read --operation Write --topic test |
只拒絕BadBob從198.168.159.3對test的讀權限 | bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --add --allow-principal User:* --allow-host * --deny-principal User:BadBob --deny-host 198.168.159.3 --operation Read --topic test |
列出test的所有權限 | bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --list --topic test |
刪除權限 | bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --remove --allow-principal User:* --allow-host * --deny-principal User:BadBob --deny-host 198.168.159.3 --operation Read --topic test |
給生產者Bob對test的生產權限 | bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --add --allow-principal User:Bob --producer --topic test |
給消費者Bob對test的消費權限 | bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --add --allow-principal User:Bob --consumer --topic test --group Group-1 |
四、MirrorMaker的跨域同步
4.1 修改kerberos配置
添加互信principle | kadmin.local下操作 addprinc krbtgt/{REALMA}@{REALMB} addprinc krbtgt/{REALMB}@{REALMA} |
修改krb5.conf | [realms]//realms 裏配上兩個域的信息 HADOOP.SPADE.COM = { kdc = hb21-bd-cm-130-61:88 admin_server = hb21-bd-cm-130-61:749 } HADOOP.TEST.COM = { kdc = tk-dba-hadoop-152:88 admin_server = tk-dba-hadoop-152:749 } [domain_realm] //domain_realm 配上域名和主機名的映射,有多少機器就要配多少 tk-dba-hadoop-154 = HADOOP.TEST.COM hb21-dba-kfk-130-120 = HADOOP.SPADE.COM
[capaths] //capaths 配上互信的域的映射 HADOOP.SAPDE.COM ={ HADOOP.TEST.COM = . } HADOOP.TEST.COM={ HADOOP.SPADE.COM = . }
|
4.2 修改broker配置
添加sasl.kerberos.principal.to.local.rules屬性
sasl.kerberos.principal.to.local.rules=RULE:[1:$1@$0](.*@\HADOOP.TEST.COM$)s/@\HADOOP.TEST.COM$//,RULE:[2:$1@$0](.*@\HADOOP.TEST.COM$)s/@\HADOOP.TEST.COM$//,RULE:[1:$1@$0](.*@\HADOOP.SPADE.COM$)s/@\HADOOP.SPADE.COM$//,RULE:[2:$1@$0](.*@\HADOOP.SPADE.COM$)s/@\HADOOP.SPADE.COM$//,DEFAULT |
4.3 驗證互信是否成功
從域B中複製出keytab到域A的機器中,然後在A中使用該keytab,配置jaas文件,導入環境變量中。用該keytab操作集羣A或者集羣B中的topic,能正常寫入數據即爲成功。
五、啓用kerberos之後的平滑過度期
生產環境啓用kerberos之後,爲了給業務向的consumer和producer一個平滑的接入認證系統的緩衝時間,這段時間我們可以給kafka啓用兩個監聽端口,一個是需要kerberos認證的端口,一個不需要認證的端口。讓他們共同存在,同時服務。
5.1 增加監聽端口
修改server.properties | listeners=SASL_PLAINTEXT://10.21.130.120:9092,PLAINTEXT://10.21.130.120:9093 allow.everyone.if.no.acl.found=false |
5.2 添加ANONYMOUS用戶的訪問權限
bin/kafka-acls.sh --add --authorizer-properties zookeeper.connect={host:port/childpath} --allow-principal User:ANONYMOUS --allow-host * --operation All --topic {topicname} |
5.3 測試不同認證方式共存成功與否
刪除jaas環境變量 | unset {變量名} |
producer測試 | bin/kafka-console-producer.sh --broker-list {host}:9093 --topic{topicname} |
六、啓用zookeeper的acl同步
kafka的bin目錄下的zookeeper-security-migration.sh,可以將kafka的權限,遍歷賦給zookeeper中每個子節點,然後分別設置acl,因爲zookeeper的acl是僅對當前節點生效,對其下節點不生效的,單獨賦權限很麻煩。zookeeper-security-migration.sh解決了這個問題。
修改server.properties,增加 zookeeper.set.acl=true |
重啓kafka集羣(批量重啓或滾動重啓) |
啓動zookeeper-security-migration.sh腳本,secure設置同步,unsecure取消同步 bin/zookeeper-security-migration --zookeeper.acl=secure --zookeeper.connect={host}:{port}/{path} |