在本系列的前几篇文章中,我们讨论了Kafka的Kerberos,LDAP和PAM身份验证。在这篇文章中,我们将研究如何配置Kafka集群和客户端以使用TLS客户端身份验证。
此处显示的示例将以粗体突出显示与身份验证相关的属性,以将其与其他必需的安全属性区分开,如下例所示。假定已为Apache Kafka集群启用了TLS,并且应该为每个安全集群启用TLS。
代码语言:javascript复制security.protocol=SSL
ssl.truststore.location=/opt/cloudera/security/jks/truststore.jks
我们将kafka-console-consumer用于以下所有示例。所有概念和配置也适用于其他应用程序。
TLS客户端身份验证
TLS客户端身份验证是Kafka支持的另一种身份验证方法。它允许客户端使用自己的TLS客户端证书连接到集群以进行身份验证。
证书管理和密钥库生成不在本文讨论范围之内,但是这些是标准的TLS做法。请注意,证书Keystores与Kerberos Keytab一样敏感,应该这样对待。密钥库许可权应始终进行限制性设置,以免它们受到损害,并且不应共享。每个客户端都应获得自己的证书。
必须设置以下Kafka客户端属性,以配置Kafka客户端以使用TLS证书进行身份验证:
代码语言:javascript复制# Uses SSL security protocolsecurity.protocol=SSLssl.keystore.location=./alice-keystore.jksssl.keystore.password=supersecret1ssl.key.password=supersecret1# TLS truststoressl.truststore.location=/opt/cloudera/security/jks/truststore.jks
上面的配置使用TLS(SSL)进行身份验证和数据加密。
在Kafka Broker上启用TLS身份验证
安装Kafka服务时,默认情况下未为Kafka代理启用TLS身份验证,但是通过Cloudera Manager对其进行配置相当容易。
默认情况下,在安全集群中,Kafka具有配置用于处理SASL_SSL身份验证的单个侦听器。要启用TLS身份验证,我们需要在其他端口上创建一个附加的侦听器来处理SSL协议。这是通过Kafka broker的listeners属性配置的。设置此属性后,我们还需要注意在其中列出原始的SASL_SSL侦听器,以确保客户端(如果正在使用的话)仍可以通过Kerberos和LDAP进行身份验证。
此外,要使用TLS客户端身份验证,我们必须确保broker和客户端相互信任彼此的证书。在前面的示例中,我们已经为客户端配置了一个信任库,其中包含代理的证书发行者的证书(ssl.truststore.location属性)。现在,如果这是与颁发代理证书的CA不同的CA ,则还必须确保已将颁发客户端证书的CA的证书添加到代理的信任库中。
我们建议客户端证书(和代理证书)由您拥有和控制的私有CA颁发。切勿将不受控制的CA证书(特别是公共CA)添加到集群信任库中。
在Cloudera Data Platform(CDP)部署中,在共享同一环境的所有集群和服务之间一致地启用TLS。该环境具有公共的共享数据体验(SDX)层,其中包含在所有环境集群之间共享的公共安全和治理上下文,并且TLS证书可以由SDX的嵌入式FreeIPA服务发行和管理。
- 在Cloudera Manager中,单击Kafka>实例> Kafka Broker(单击单个代理)> Configuration 。将显示一个警报,您可以通过单击“继续编辑角色实例”将其忽略。
- 为Kafka代理设置以下属性(使用您自己的代理的标准主机名)并保存配置。我们在此安全阀中同时设置了两个不同的属性:listeners和ssl.principal.mapping.rules 。请在listeners属性中注意每个侦听器的不同协议和端口。
- 对所有其他代理重复该过程。
- 现在在服务级别上设置以下内容,单击Kafka>配置,然后在下面的配置中选中“ required ”。保存您的更改:
- 如上所述,Kafka需要信任颁发给您的客户的证书。如果这些证书是由与Kafka Broker证书不同的CA签名的,则需要将客户端证书的CA添加到Kafka信任库中。您可以在Cloudera Manager的以下属性中找到信任库的位置:
- 运行以下命令(以root身份)将CA证书添加到信任库中:
keytool -importcert -keystore /opt/cloudera/security/jks/truststore.jks -storetype JKS -alias ldap-ca -file /path/to/ca-cert.pem
- 单击Kafka>操作>重新启动以重新启动Kafka服务并使更改生效。
安全中间代理协议
代理间通信所使用的安全协议由Kafka的security.inter.broker.protocol属性控制。Cloudera Manager将此属性的默认设置设置为INFERRED 。
在此配置中,CM将根据以下逻辑设置security.inter.broker.protocol属性:
- 如果正在使用Kerberos或LDAP身份验证:
- 如果启用了TLS,请将其设置为SASL_SSL
- 如果未启用TLS,请将其设置为SASL_PLAINTEXT
- 除此以外:
- 如果启用了TLS,请将其设置为SSL
- 如果未启用TLS,请将其设置为PLAINTEXT
如果您使用不同的安全协议定义了多个侦听器,并且推断的中间代理协议不是您要使用的协议,则可以使用上面显示的属性覆盖。
Principal名称映射
当客户端使用TLS密钥库进行身份验证时,默认情况下,Kafka会假定该客户端的用户名是证书的使用者名称,通常是可分辨名称,如下所示:
cn=alice,cn=groups,cn=accounts,dc=hadoopsecurity,dc=local
使用这些长名称很麻烦。安全策略和组映射通常是根据用户的简称(alice )而不是完整的专有名称来定义的。因此,我们需要配置Kafka以将证书的主题转换为短名称,我们可以将其用作用户的唯一标识符。
如果您使用的是Kafka 2.4.0 (*)或更高版本,则可以通过使用必要的映射规则设置ssl.principal.mapping.rules参数来完成此操作。对于较旧的版本,您可以提供一个自定义的主体构建器。创建定制构建器超出了本文档的范围,但是您可以在此处找到一个很好的示例。
该规则采用正则表达式的形式来匹配证书的使用者名称,并应用转换来匹配。可以有多个规则,以逗号分隔。最后一条规则通常是DEFAULT规则,它仅使用完整的主题名称
例如,考虑以下设置:
代码语言:javascript复制ssl.principal.mapping.rules=RULE:^.*[Cc][Nn]=([a-zA-Z0-9.]*).*$/$1/L,DEFAULT
上面的配置有2条规则,它们按顺序处理:
代码语言:javascript复制RULE:^[Cc][Nn]=([a-zA-Z0-9.]*).*$/$1/LDEFAULT
将使用与证书的主题名称匹配的第一个规则,而后一个规则将被忽略。该默认规则是“包罗万象的”。如果以前的匹配项都不匹配,它将始终匹配并且不会进行任何替换。
上面第一个规则的正则表达式(^[Cc][Nn]=([a-zA-Z0-9.]*).*$)将匹配以CN = (或:cn = ,Cn = ,cN =),后跟用户的简称(应仅包含以下字符:a-zA-Z0-9.),后跟任何其他字符。它用用户短名称替换匹配的字符串,该用户短名称是括号内匹配的内容,在规则的第二部分中以$ 1引用。您可以在实际操作中看到它,并在此处使用正则表达式和示例。
规则末尾的L将结果字符串转换为小写。您可以在Kafka官方文档中看到更多详细信息和规则示例。
证书吊销列表
证书吊销列表(或CRL)是已颁发证书的证书颁发机构(CA)在其计划的到期日期之前已将其撤消的数字证书的列表,并且不再受信任。CRL是TLS身份验证的重要功能,可确保可以将已被破坏的客户端证书标记为已过期,以便Kafka代理拒绝来自使用它们的客户端的连接。
尽管Kafka尚未直接支持CRL的使用(请参阅KAFKA-3700),但是Java框架中提供了该选项。可以通过CRL分发点(CRLDP)或通过在线证书状态协议(OCSP)来执行吊销检查。要使用这两种方法中的任何一种,必须首先确保使用这些方法之一将证书颁发机构(CA)正确配置为进行证书吊销检查,并且证书中包含用于此操作的必要信息。CA的配置和具有正确属性的证书的生成不在本文档的范围之内。
要为Kafka启用证书吊销检查,请执行以下步骤:
要使用CRLDP启用吊销检查:
a.在Cloudera Manager中,转到Kafka>配置,然后搜索Additional Broker Java Options属性。
b.将以下值附加到该属性的末尾:
代码语言:javascript复制-Dcom.sun.security.enableCRLDP=true
-Dcom.sun.net.ssl.checkRevocation=true
要使用OCSP启用吊销检查:
a.除了上述针对CRLDP的属性外,还将以下值附加到同一属性的末尾:
-Djava.security.properties=<(echo "ocsp.enable=true")
进行以上任何更改后,都必须重新启动Kafka服务。如果在CA和证书中未正确配置对CRLDP和/或OCSP的支持,则该服务可能无法启动。
即使未启用证书吊销,也可以通过确保吊销和/或拒绝所有适用于那些证书的授权策略(通过Ranger,Sentry或ACL)来阻止对Kafka资源的访问。
示例
以下是使用Kafka控制台使用者使用TLS身份验证从主题读取的示例。请注意,在连接到集群时,我们使用SSL侦听器的端口(9094)而不是默认的9093提供引导服务器。
代码语言:javascript复制$ cat tls-client.propertiessecurity.protocol=SSLssl.keystore.location=./alice-keystore.jksssl.keystore.password=supersecret1ssl.key.password=supersecret1ssl.truststore.location=/opt/cloudera/security/jks/truststore.jks $ kafka-console-consumer --bootstrap-server host-1.example.com:9094 --topic test --consumer.config ./tls-client.properties
注意:上面的客户端配置包含敏感的凭据。将此配置存储在文件中时,请确保已设置文件许可权,以便只有文件所有者才能读取它。
还有更多
我们将在本博客系列中回顾所有这些身份验证方法,这些方法为您提供了灵活的配置Kafka集群的方法,以便与适用于您的环境的身份验证机制集成在一起。
我们将在本系列的下一篇文章中继续探索其他身份验证替代方案。同时,如果您有兴趣了解Cloudera的Kafka产品,请下载此白皮书。
(*)ssl.principal.mapping.rules属性自Kafka 2.2.0起可用,但不能处理证书专有名称(KAFKA-8860)中的空格。Kafka 2.4.0是更强大的起点。
原文作者:Andre Araujo
原文链接:https://blog.cloudera.com/how-to-configure-clients-to-connect-to-apache-kafka-clusters-securely-part-4-tls-client-authentication/