为 Azure HDInsight 中的非 ESP Apache Kafka 群集设置 TLS 加密和身份验证

本文介绍如何在 Apache Kafka 客户端与 Apache Kafka 代理之间设置传输层安全性 (TLS) 加密(以前称为安全套接字层 (SSL) 加密)。 此外还介绍了如何设置客户端的身份验证(有时称为双向 TLS)。

重要

有两个客户端可用于 Kafka 应用程序:一个 Java 客户端和一个控制台客户端。 只有 Java 客户端 ProducerConsumer.java 可以通过 TLS 来实现生成和使用。 控制台生成方客户端 console-producer.sh 不能与 TLS 配合工作。

Apache Kafka 代理设置

Kafka TLS 代理设置按以下方式使用四个 HDInsight 群集 VM:

  • 头节点 0 - 证书颁发机构 (CA)
  • 工作器节点 0、1 和 2 - 代理

注意

本指南使用自签名证书,但最安全的解决方案是使用受信任 CA 颁发的证书。

代理设置过程的摘要如下:

  1. 在每个工作器节点(共三个)上重复以下步骤:

    1. 生成证书。
    2. 创建证书签名请求。
    3. 将证书签名请求发送到证书颁发机构 (CA)。
    4. 登录到 CA 并为请求签名。
    5. 通过 SCP 将签名的证书发回给工作器节点。
    6. 通过 SCP 将 CA 的公共证书发送给工作器节点。
  2. 获取所有证书后,将证书放入证书存储。

  3. 转到 Ambari 并更改配置。

    遵照以下详细说明完成代理设置:

    重要

    在以下代码片段中,wnX 是三个工作器节点中某个节点的缩写,应该相应地将其替换为 wn0wn1wn2。 应将 WorkerNode0_NameHeadNode0_Name 替换为相应计算机的名称。

  4. 在头节点 0 上执行初始设置,使 HDInsight 填充证书颁发机构 (CA) 的角色。

    # Create a new directory 'ssl' and change into it
    mkdir ssl
    cd ssl
    
  5. 在每个代理(工作器节点 0、1 和 2)上执行相同的初始设置。

    # Create a new directory 'ssl' and change into it
    mkdir ssl
    cd ssl
    
  6. 在每个工作器节点上,使用代码片段执行以下步骤。

    1. 创建密钥存储并在其中填充新的专用证书。
    2. 创建证书签名请求。
    3. 通过 SCP 将证书签名请求发送给 CA(头节点 0)
    keytool -genkey -keystore kafka.server.keystore.jks -keyalg RSA -validity 365 -storepass "MyServerPassword123" -keypass "MyServerPassword123" -dname "CN=FQDN_WORKER_NODE" -ext SAN=DNS:FQDN_WORKER_NODE -storetype pkcs12
    keytool -keystore kafka.server.keystore.jks -certreq -file cert-file -storepass "MyServerPassword123" -keypass "MyServerPassword123"
    scp cert-file sshuser@HeadNode0_Name:~/ssl/wnX-cert-sign-request
    

    注意

    FQDN_WORKER_NODE 是工作器节点计算机的完全限定域名。可以从头节点中的 /etc/hosts 文件获取该详细信息

    例如,

    wn0-espkaf.securehadooprc.partner.onmschina.cn
    wn0-kafka2.zbxwnwsmpcsuvbjqbmespcm1zg.bx.internal.chinacloudapp.cn
    

    显示主机文件输出的屏幕截图。

  7. 在 CA 计算机上,运行以下命令创建 ca-cert 和 ca-key 文件:

    openssl req -new -newkey rsa:4096 -days 365 -x509 -subj "/CN=Kafka-Security-CA" -keyout ca-key -out ca-cert -nodes
    
  8. 切换到 CA 计算机,为所有收到的证书签名请求签名:

    openssl x509 -req -CA ca-cert -CAkey ca-key -in wn0-cert-sign-request -out wn0-cert-signed -days 365 -CAcreateserial -passin pass:"MyServerPassword123"
    openssl x509 -req -CA ca-cert -CAkey ca-key -in wn1-cert-sign-request -out wn1-cert-signed -days 365 -CAcreateserial -passin pass:"MyServerPassword123"
    openssl x509 -req -CA ca-cert -CAkey ca-key -in wn2-cert-sign-request -out wn2-cert-signed -days 365 -CAcreateserial -passin pass:"MyServerPassword123"
    
  9. 将已签名的证书从 CA(头节点 0)发回给工作器节点。

    scp wn0-cert-signed sshuser@WorkerNode0_Name:~/ssl/cert-signed
    scp wn1-cert-signed sshuser@WorkerNode1_Name:~/ssl/cert-signed
    scp wn2-cert-signed sshuser@WorkerNode2_Name:~/ssl/cert-signed
    
  10. 将 CA 的公共证书发送给每个工作器节点。

    scp ca-cert sshuser@WorkerNode0_Name:~/ssl/ca-cert
    scp ca-cert sshuser@WorkerNode1_Name:~/ssl/ca-cert
    scp ca-cert sshuser@WorkerNode2_Name:~/ssl/ca-cert
    
  11. 在每个工作器节点上,将 CA 公共证书添加到信任存储和密钥存储。 然后,将工作器节点自身的已签名证书添加到密钥存储

    keytool -keystore kafka.server.truststore.jks -alias CARoot -import -file ca-cert -storepass "MyServerPassword123" -keypass "MyServerPassword123" -noprompt
    keytool -keystore kafka.server.keystore.jks -alias CARoot -import -file ca-cert -storepass "MyServerPassword123" -keypass "MyServerPassword123" -noprompt
    keytool -keystore kafka.server.keystore.jks -import -file cert-signed -storepass "MyServerPassword123" -keypass "MyServerPassword123" -noprompt
    
    

将 Kafka 配置更新为使用 TLS 并重启代理

现已为每个 Kafka 代理设置了密钥存储和信任存储,并导入了正确的证书。 接下来,请使用 Ambari 修改相关的 Kafka 配置属性,然后重启 Kafka 代理。

若要完成配置修改,请按照以下步骤操作:

  1. 登录到 Azure 门户,并选择你的 Azure HDInsight Apache Kafka 群集。

  2. 单击群集仪表板下面的“Ambari 主页”转到 Ambari UI。

  3. 在“Kafka 代理”下,将 listeners 属性设置为 PLAINTEXT://localhost:9092,SSL://localhost:9093

  4. 在“高级 kafka-broker”下,将 security.inter.broker.protocol 属性设置为 SSL

    在 Ambari 中编辑 Kafka ssl 配置属性。

  5. 在“自定义 kafka-broker”下,将 ssl.client.auth 属性设置为 required

    注意

    注意:仅当同时设置了身份验证和加密时,才需要执行此步骤。

    在 Ambari 中编辑 Kafka ssl 配置属性。

  6. 以下屏幕截图显示了具有这些更改的 Ambari 配置 UI。

    注意

    1. ssl.keystore.location 和 ssl.truststore.location 是密钥存储的完整路径,证书颁发机构中的信任存储位置 (hn0)
    2. ssl.keystore.password 和 ssl.truststore.password 是为密钥存储和信任存储设置的密码。 在此示例中为 MyServerPassword123
    3. ssl.key.password 是为密钥存储和信任存储设置的密钥。 在此示例中为 MyServerPassword123
  7. 在 Kafka 中使用 TLS 1.3

    将以下配置添加到 Ambari 中的 kafka 配置

    1. ssl.enabled.protocols=TLSv1.3
    2. ssl.protocol=TLSv1.3

    重要

    1. TLS 1.3 仅适用于 HDI 5.1 kafka 版本。
    2. 如果在服务器端使用 TLS 1.3,则也应在客户端使用 TLS 1.3 配置。
  8. 对于 HDI 版本 4.0 或 5.0

    1. 如果要设置身份验证和加密,则屏幕截图如下所示

    在 Ambari 4 中编辑 kafka-env 模版属性。

    1. 如果仅设置加密,则屏幕截图如下所示

    显示如何在 Ambari 中仅出于加密目的编辑 kafka-env 模板属性字段的屏幕截图。

  9. 重启所有 Kafka 代理。

客户端设置(不使用身份验证)

如果不需要身份验证,仅设置 TLS 加密的步骤概括如下:

  1. 登录到 CA(活动头节点)。
  2. 将 CA 证书从 CA 计算机 (wn0) 复制到客户端计算机。
  3. 登录到客户端计算机 (hn1),并导航到 ~/ssl 文件夹。
  4. 将 CA 证书导入信任存储。
  5. 将 CA 证书导入密钥存储。

以下代码片段中详细说明了这些步骤。

  1. 登录到 CA 节点。

    ssh sshuser@HeadNode0_Name
    cd ssl
    
  2. 将 CA 证书复制到客户端计算机

    scp ca-cert sshuser@HeadNode1_Name:~/ssl/ca-cert
    
  3. 登录到客户端计算机(待机头节点)。

    ssh sshuser@HeadNode1_Name
    cd ssl
    
  4. 将 CA 证书导入信任存储。

    keytool -keystore kafka.client.truststore.jks -alias CARoot -import -file ca-cert -storepass "MyClientPassword123" -keypass "MyClientPassword123" -noprompt
    
  5. 将 CA 证书导入密钥存储。

    keytool -keystore kafka.client.keystore.jks -alias CARoot -import -file ca-cert -storepass "MyClientPassword123" -keypass "MyClientPassword123" -noprompt
    
  6. 在客户端计算机 (hn1) 上创建 client-ssl-auth.properties 文件。 该文件应包含以下行:

    security.protocol=SSL
    ssl.truststore.location=/home/sshuser/ssl/kafka.client.truststore.jks
    ssl.truststore.password=MyClientPassword123
    
    1. 若要使用 TLS 1.3,请将以下配置添加到文件 client-ssl-auth.properties
    ssl.enabled.protocols=TLSv1.3
    ssl.protocol=TLSv1.3
    
  7. 使用生成方和使用方选项启动管理客户端,以验证生成方和使用方是否在端口 9093 上运行。 请参阅验证部分,了解使用控制台生成端/使用端验证设置所需的步骤。

客户端设置(使用身份验证)

注意

仅当同时设置了 TLS 加密和身份验证时,才需要执行以下步骤。 如果仅设置加密,请参阅不使用身份验证的客户端设置

以下四个步骤汇总了完成客户端安装所要执行的任务:

  1. 登录到客户端计算机(待机头节点)。
  2. 创建 Java 密钥存储并获取代理的已签名证书。 然后将该证书复制到运行 CA 的 VM。
  3. 切换到 CA 计算机(活动头节点),为客户端证书签名。
  4. 转到客户端计算机(待机头节点),并导航到 ~/ssl 文件夹。 将已签名的证书复制到客户端计算机。

已提供每个步骤的详细信息。

  1. 登录到客户端计算机(待机头节点)。

    ssh sshuser@HeadNode1_Name
    
  2. 删除任何现有的 ssl 目录。

    rm -R ~/ssl
    mkdir ssl
    cd ssl
    
  3. 创建 Java 密钥存储,并创建证书签名请求。

    keytool -genkey -keystore kafka.client.keystore.jks -validity 365 -storepass "MyClientPassword123" -keypass "MyClientPassword123" -dname "CN=HEADNODE1_FQDN" -storetype pkcs12
    
    keytool -keystore kafka.client.keystore.jks -certreq -file client-cert-sign-request -storepass "MyClientPassword123" -keypass "MyClientPassword123"
    
  4. 将证书签名请求复制到 CA

    scp client-cert-sign-request sshuser@HeadNode0_Name:~/ssl/client-cert-sign-request
    
  5. 切换到 CA 计算机(活动头节点),并为客户端证书签名。

    ssh sshuser@HeadNode0_Name
    cd ssl
    openssl x509 -req -CA ca-cert -CAkey ca-key -in ~/ssl/client-cert-sign-request -out ~/ssl/client-cert-signed -days 365 -CAcreateserial -passin pass:MyClientPassword123
    
  6. 将签名的客户端证书从 CA(活动头节点)复制到客户端计算机。

    scp client-cert-signed sshuser@HeadNode1_Name:~/ssl/client-signed-cert
    
  7. 将 CA 证书复制到客户端计算机

    scp ca-cert sshuser@HeadNode1_Name:~/ssl/ca-cert
    
    1. 登录到客户端计算机(待机头节点),并导航到 ssl 目录。
    ssh sshuser@HeadNode1_Name
    cd ssl
    
  8. 创建包含已签名证书的客户端存储,将 CA 证书导入客户端计算机 (hn1) 上的密钥存储和信任存储:

    keytool -keystore kafka.client.truststore.jks -alias CARoot -import -file ca-cert -storepass "MyClientPassword123" -keypass "MyClientPassword123" -noprompt
    
    keytool -keystore kafka.client.keystore.jks -alias CARoot -import -file ca-cert -storepass "MyClientPassword123" -keypass "MyClientPassword123" -noprompt
    
    keytool -keystore kafka.client.keystore.jks -import -file client-signed-cert -storepass "MyClientPassword123" -keypass "MyClientPassword123" -noprompt
    
  9. 在客户端计算机 (hn1) 上创建文件 client-ssl-auth.properties。 该文件应包含以下行:

    security.protocol=SSL
    ssl.truststore.location=/home/sshuser/ssl/kafka.client.truststore.jks
    ssl.truststore.password=MyClientPassword123
    ssl.keystore.location=/home/sshuser/ssl/kafka.client.keystore.jks
    ssl.keystore.password=MyClientPassword123
    ssl.key.password=MyClientPassword123
    
    1. 若要使用 TLS 1.3,请将以下配置添加到文件 client-ssl-auth.properties
    ssl.enabled.protocols=TLSv1.3
    ssl.protocol=TLSv1.3
    

验证

在客户端计算机上运行这些步骤。

注意

如果已安装 HDInsight 4.0 和 Kafka 2.1,可以使用控制台生成端/使用端来验证设置。 如果未安装,请在端口 9092 上运行 Kafka 生成端并向主题发送消息,然后在端口 9093 上运行使用 TLS 的 Kafka 使用端。

Kafka 2.1 或更高版本

  1. 如果主题尚不存在,请创建一个主题。

    /usr/hdp/current/kafka-broker/bin/kafka-topics.sh --zookeeper <ZOOKEEPER_NODE>:2181 --create --topic topic1 --partitions 2 --replication-factor 2
    
  2. 启动控制台生成端,并以配置文件的形式为生成端提供 client-ssl-auth.properties 的路径。

    /usr/hdp/current/kafka-broker/bin/kafka-console-producer.sh --broker-list <FQDN_WORKER_NODE>:9093 --topic topic1 --producer.config ~/ssl/client-ssl-auth.properties
    
  3. 与客户端计算机建立另一个 SSH 连接,启动控制台使用端,并以配置文件的形式为使用端提供 client-ssl-auth.properties 的路径。

    /usr/hdp/current/kafka-broker/bin/kafka-console-consumer.sh --bootstrap-server <FQDN_WORKER_NODE>:9093 --topic topic1 --consumer.config ~/ssl/client-ssl-auth.properties --from-beginning
    

后续步骤