7.3 使用SASL实现身份验证

优质
小牛编辑
141浏览
2023-12-01
  1. JAAS 的配置

    Kafka 使用Java验证和授权API(JAAS)来完成 SASL 配置.

    1. Kafka brokers 的 JAAS 的配置

      KafkaServer 是每一个 KafkaServer/Broker 的 JASS 文件里面的节点名称。 在这个节点中,提供了用于所有 brokers 之间通信的 SASL 客户端连接的 SASL 配置选项。

      Client 节点是用于认证 SASL 与 zookeeper 之间的连接。它也允许 brokers 通过设定 zookeeper 节点中 SASL ACL 来锁定这些节点 从而确定这些节点不被其他 broker 修改。 在所有的 broker 中都必须使用相同的名称。 如果您想使用 Client 以外名称, 请设置系统属性 zookeeper.sasl.clientconfig 中填写合适的名称 (e.g., -Dzookeeper.sasl.clientconfig=ZkClient).

      ZooKeeper 使用 "zookeeper" 作为默认的名称. 如果您想改变它的话, 请设置系统属性 zookeeper.sasl.client.username 中填写合适的名称 (e.g., -Dzookeeper.sasl.client.username=zk).

    2. Kafka clients 的 JAAS 的配置

      Client 通过配置客户端属性 sasl.jaas.config 或者通过与 brokers 相似的方法来配置 JAAS (static JAAS config file)

      1. 通过客户端配置属性来配置JAAS

        客户无需创建物理文件来配置角色 只需要在 JASS 配置中指定 producer 或者 consumer。 这种模式通过为每个客户端指定不同的属性来使用不同的凭证,从而确保可以在在同一个 JVM 中使用不同的 producers 和 consumers。如果静态JAAS配置系统属性的方法 java.security.auth.login.config 和配置客户端属性 sasl.jaas.config的方法 同时被使用, 客户端的配置将会被使用.

        请看 GSSAPI (Kerberos), PLAIN or SCRAM 中的示例配置。

      2. 通过静态配置文件来配置 JAAS
        使用静态 JAAS 配置文件 来配置 SASL 的客户端认证服务:
        1. 添加一个名为 KafkaClient 客户端的登陆节点,同时为 KafkaClient 中所选机制来配置一个登陆模块 如设置GSSAPI (Kerberos), PLAIN 或者 SCRAM。 例如, GSSAPI 的凭证配置如下:
              KafkaClient {    com.sun.security.auth.module.Krb5LoginModule required    useKeyTab=true    storeKey=true    keyTab="/etc/security/keytabs/kafka_client.keytab"    principal="kafka-client-1@EXAMPLE.COM";};
        2. 将 JASS 的配置文件位置作为 JVM 的参数传递给每个客户端的 JVM。 例如:
              -Djava.security.auth.login.config=/etc/kafka/kafka_client_jaas.conf
  2. SASL 的配置

    SASL 可以使用 PLAINTEXT 或者 SSL 协议作为传输层,相对应的就是使用 SASL_PLAINTEXT 或者 SASL_SSL 安全协议。 如果使用 SASL_SSL 安全协议,必须配置 SSL证书。

    1. SASL 安全机制

      Kafka 支持以下的四个 SASL 机制:
      • GSSAPI (Kerberos)
      • PLAIN
      • SCRAM-SHA-256
      • SCRAM-SHA-512
    2. Kafka brokers 的SASL配置

      1. 在 server.properties 文件中配置一个 SASL 端口, 要为 listeners 添加其中至少一个参数(SASL_PLAINTEXT 或者 SASL_SSL):
            listeners=SASL_PLAINTEXT://host.name:port
        如果您只配置一个 SASL 端口 (或者您只想希望在 Kafka brokersz 之间使用 SASL 协议相互认证的话)您需要确保您在 borker 之间通信中 使用了了相同的 SASL 协议。
            security.inter.broker.protocol=SASL_PLAINTEXT (or SASL_SSL)
      2. 选择一个或者多个 支持的安全机制 然后按照所给的步骤来为所选的安全机制配置 SASL 协议。 如果您想在 broker 中启用多个安全机制, 请根据此处步骤操作。
    3. Kafka 客户端配置 SASL

      SASL 授权只在新的 Java Kafka producer and consumer API 中被支持。之前的API并不支持

      要在客户端配置 SASL 授权, 需在 broker 中选择一个已启用的SASL 机制用于客户端授权 并且根据下面的步骤为所选的安全机制配置 SASL 协议。

  3. 使用 SASL/Kerberos 认证协议

    1. 准备条件

      1. Kerberos
        如果您的项目已经使用 Kerberos 认证协议服务器(例如使用了Active Directory),那么您就无需为 Kafka 安装新的服务器,否则您需要从您 Linux 社区中的服务包中安装一个。 此处有一个简短的指南教您如何安装并且配置它(Ubuntu,Redhat). 请注意,若果您正在使用 Oracle Java, 您需要对应您的 Java 版本 下载 JCE 策略文件,并且将它拷贝到 $JAVA_HOME/jre/lib/security 路径下面。
      2. 创建 Kerberos 证书
        如果您在使用团队的 Kerberos 服务器或者 Active Directory 服务器, 请向您的 Kerberos 管理员咨询集群中每一个 Kafka broker 的证书 和 每个将通过 Kerberos 身份验证的用户的证书(通过客户端或者工具等方式通过身份验证)。
        如果您已经安装了自己的 Kerberos, 您可以根据下面的步骤为您自己创建证书:
            sudo /usr/sbin/kadmin.local -q 'addprinc -randkey kafka/{hostname}@{REALM}'    sudo /usr/sbin/kadmin.local -q "ktadd -k /etc/security/keytabs/{keytabname}.keytab kafka/{hostname}@{REALM}"
      3. 确保所有的主机名可以访问其对应的主机 - Kerberos 要求您的所有主机都可以被其 FQDN 进行解析。
    2. Kafka Brokers 的配置

      1. 为每一个 Kafka broker 的 config 目录下,创建一个类似下面的适当修改的 JAAS 文件,我们在这个例子中把它命名为 kafka_server_jaas.conf (请注意每一个 broker 都应该有他自己 keytab):
            KafkaServer {        com.sun.security.auth.module.Krb5LoginModule required        useKeyTab=true        storeKey=true        keyTab="/etc/security/keytabs/kafka_server.keytab"        principal="kafka/kafka1.hostname.com@EXAMPLE.COM";    };
         // Zookeeper client authentication    Client {    com.sun.security.auth.module.Krb5LoginModule required    useKeyTab=true    storeKey=true    keyTab="/etc/security/keytabs/kafka_server.keytab"    principal="kafka/kafka1.hostname.com@EXAMPLE.COM";    };
      2. JAAS 文件中 的 KafkaServer 节点 告诉 broker 使用哪一个认证以及对应的认证的 keytab 的位置。 它允许 broker 根据节点中的 keytab 中的信息来认证登陆。 有关 Zookeeper SASL 配置的更多详细信息,请参阅 此处。
      3. 将 JAAS 和 krb5(可选)的文件位置作为 JVM 的参数传给每一个 Kafka broker。获取更多资料请参照 此处
            -Djava.security.krb5.conf=/etc/kafka/krb5.conf    -Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf
      4. 确保启动 Kafka broker 的操作系统用户可以读取 JAAS 文件中的 keytabs。
      5. 在配置server.properties文件中,确保SASL 端口 和 SASL 安全机制配置正确. 例如:
            listeners=SASL_PLAINTEXT://host.name:port    security.inter.broker.protocol=SASL_PLAINTEXT    sasl.mechanism.inter.broker.protocol=GSSAPI    sasl.enabled.mechanisms=GSSAPI        
      6. 我们在 server.properties 文件中, 必须配置和 Kafka broker 证书中名称相匹配的服务器名称。 在下面的例子中, 证书的名称为"kafka/kafka1.hostname.com@EXAMPLE.com",所以
            sasl.kerberos.service.name=kafka
    3. Kafka 客户端的配置

      在客户端配置 SASL 认证:
      1. 客户端 (producers, consumers, connect workers, 等等) 将使用自己的证书对集群进行身份验证(证书的名字通常与运行客户端的用户同名) 然后根据需要来创建或者获取证书。从而为每一个客户端配置 JAAS 配置属性。 通过指定不同的证书, JVM的不同客户端可以作为不同的用户运行。 在 producer.properties 或者 consumer.properties 文件中 sasl.jaas.config 属性描述着客户端(producer 或 consumer)通过何种方式连接 Kafka broker。 下面的例子是使用 keytab 配置客户端(建议用于长时间运行的进程):
        sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \    useKeyTab=true \    storeKey=true  \    keyTab="/etc/security/keytabs/kafka_client.keytab" \    principal="kafka-client-1@EXAMPLE.COM";
        对于像 kafka-console-consumer 和 kafka-console-producer 这样的命令行应用程序, kinit 可以与 "useTicketCache=true" 一同使用。就像:
        sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \    useTicketCache=true;
        客户端的 JAAS 配置 也可以设定为与此处所述的 broker 类似的参数。 客户端使用登陆的节点名称(KafkaClient)的这个选项只来确保 一个 JVM 的所有的客户端只对应一个用户。
      2. 确保启动 Kafka broker 的操作系统用户可以读取 JAAS 文件中的 keytabs。
      3. (可选)将 krb5 的文件位置作为 JVM 的参数传给每一个 Kafka broker。获取更多资料请参照此处
            -Djava.security.krb5.conf=/etc/kafka/krb5.conf
      4. 在 producer.properties 和 consumer.properties 文件中配置以下的属性:
        security.protocol=SASL_PLAINTEXT (or SASL_SSL)sasl.mechanism=GSSAPIsasl.kerberos.service.name=kafka
  4. 使用 SASL/PLAIN 认证

    SASL/PLAIN 是一种简单的 username/password 认证机制, 通常与 TLS 加密一起使用, 用于实现安全认证. Kafka 提供了一个默认的 SASL/PLAIN 实现, 可以做扩展后在生产环境使用, 如 这里 的描述.

    username 在 ACL 等的配置中作为已认证的 Principal.
    1. 配置 Kafka Broker

      1. 在每一个 Kafka broker 的 config 目录中, 添加一个类似于下面的适当修改过的 JAAS 文件. 在这个例子中, 让我们将它命名为 kafka_server_jaas.conf:
            KafkaServer {        org.apache.kafka.common.security.plain.PlainLoginModule required        username="admin"        password="admin-secret"        user_admin="admin-secret"        user_alice="alice-secret";    };
        这个配置定义了两个用户 (admin and alice). broker 使用在 KafkaServer 部分的 usernamepassword 属性初始化与其他 broker 的连接. 在这个例子中, admin 是 broker 间通信的用户. user_userName 属性的值定义了所有连接到 broker 的用户的密码. 这个 broker 验证所有客户端的连接, 包括那些使用了这些配置的 broker 的连接.
      2. 将 JAAS 配置文件的路径作为 JVM 的参数, 并传递到每一个 Kafka broker:
            -Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf
      3. 如 这里 描述的, 在 server.properties 中配置 SASL 端口和 SASL 机制. 例如:
            listeners=SASL_SSL://host.name:port    security.inter.broker.protocol=SASL_SSL    sasl.mechanism.inter.broker.protocol=PLAIN    sasl.enabled.mechanisms=PLAIN
    2. 配置 Kafka Client

      在客户端上配置 SASL 验证:
      1. 在每一个客户端的 producer.properties 或者 consumer.properties 中配置 JAAS 属性. 登录模块描述了像生产者和消费者这样的客户端如何连接到 Kafka Broker. 下面是一个 PLAIN 机制的客户端的配置示例:
        sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \    username="alice" \    password="alice-secret";

        usernamepassword 选项被客户端用于配置客户端连接的用户. 在这个例子中, 客户端以 alice 用户连接到 broker. 通过在 sasl.jaas.config 中指定不同的用户名和密码, 在一个 JVM 内不同的客户端可以以不同的用户连接.

        客户端的 JAAS 配置也可以像 这里 描述的 broker 一样, 指定为一个 JVM 参数. 客户端使用名为 KafkaClient 的登录部分. 此选项仅允许来自 JVM 的所有客户端连接中的一个用户.

      2. 在 producer.properties 或者 consumer.properties 中配置下面这些属性:
        security.protocol=SASL_SSLsasl.mechanism=PLAIN
    3. 在生产环境中使用 SASL/PLAIN

      • SASL/PLAIN 应该只用 SSL 作为传输层, 以保证在没有加密的情况下不会在线上传输明文密码.
      • Kafka 中 SASL/PLAIN 的默认实现是在 JAAS 配置文件声明用户名和密码, 如 这里 展示的. 为了避免在磁盘上保存密码, 你可以实现你自己的 javax.security.auth.spi.LoginModule, 从一个外部源提供用户名和密码. 登录模块的实现应该提供 Subject 的用户名作为公共证书和密码作为私有的凭证. org.apache.kafka.common.security.plain.PlainLoginModule 的默认实现可以作为参考例子.
      • 在生产系统, 外部的认证服务可以实现密码认证. 通过添加你自己的 javax.security.sasl.SaslServer 实现, Kafka brokers 可以和这些服务集成. Kafka 中的默认实现在 org.apache.kafka.common.security.plain 包中, 可以作为开始学习的例子.
        • 新的提供者一定要在 JVM 中安装和注册. 可以通过添加提供类到平常的 CLASSPATH, 或者把提供类打包成 jar 文件并添加到JAVA_HOME/lib/ext中来安装提供者.
        • 将提供者添加到安全属性文件 (security properties file) JAVA_HOME/lib/security/java.security 静态注册提供者.
              security.provider.n=providerClassName
          其中 providerClassName 是新提供者的全称. n 是优先顺序, 比较小的数字表明更高的优先级.
        • 此外, 你可以在运行时通过在客户端程序开始时或者在登录模块的一个静态初始化程序中唤起 Security.addProvider来动态的注册提供者. 例如:
              Security.addProvider(new PlainSaslServerProvider());
        • 更多细节, 请查看 JCA Reference.
  5. 使用 SASL/SCRAM 认证

    Salted Challenge Response Authentication Mechanism (SCRAM) 是 SASL 机制家族中的一员, 是用传统的机制解决安全问题, 执行像 PLAIN 和 DIGEST-MD5 一样的 username/password 认证. 这个机制在 RFC 5802 定义. Kafka 支持 SCRAM-SHA-256 和 SCRAM-SHA-512, 可以和 TLS 一起用户执行安全认证. username 在 ACL 等的配置中作为已认证的 Principal. Kafka 中默认的 SCRAM 实现是在 Zookeeper 中保存 SCRAM 证书, 适用于 Zookeeper 在私有网络的 Kafka 安装. 更多信息请查看 安全注意事项.

    1. 创建 SCRAM 证书

      Kafka 中的 SCRAM 实现使用 Zookeeper 作为证书存储. 可以使用 kafka-configs.sh 在 Zookeeper 中创建证书. 对每一个启用了 SCRAM 机制的, 必须通过添加机制名配置来创建证书. 用于 broker 间通信的证书必须在 Kafka broker 启动前创建. 客户端的证书可以动态创建和更新, 新的连接使用更新后的证书认证.

      为用户 alice 创建密码为 alice-secret 的 SCRAM 凭证:

      > bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=alice-secret],SCRAM-SHA-512=[password=alice-secret]' --entity-type users --entity-name alice    

      如果未指定迭代次数, 将使用默认的迭代次数, 4096. 创建一个随机 salt, SCRAM 标识由 salt, 迭代和 StoredKey 组成. ServerKey 保存在 Zookeeper 中. 有关 SCRAM 的标识和各个字段的详细信息,请参考 RFC 5802.

      以下示例中, 关于 broker 间的通信, 需要一个 admin 用户. 使用如下命令创建:

      > bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config 'SCRAM-SHA-256=[password=admin-secret],SCRAM-SHA-512=[password=admin-secret]' --entity-type users --entity-name admin    

      使用 --describe 选项可以 列出所有存在的证书:

      > bin/kafka-configs.sh --zookeeper localhost:2181 --describe --entity-type users --entity-name alice    

      使用 --delete 选项删除一个或多个 SCRAM 机制的证书:

      > bin/kafka-configs.sh --zookeeper localhost:2181 --alter --delete-config 'SCRAM-SHA-512' --entity-type users --entity-name alice    

    2. 配置 Kafka Broker

      1. 在每个 Kafka broker 的 config 目录, 添加一个类似下面的适当修改的 JAAS 文件. 在这个例子中, 我们将其命名为 kafka_server_jaas.conf:
        KafkaServer {    org.apache.kafka.common.security.scram.ScramLoginModule required    username="admin"    password="admin-secret";};
        broker 使用 KafkaServer 部分中 usernamepassword 属性来初始化与其他 broker 的连接. 在这个例子中, admin 是 broker 间通信的用户.
      2. JAAS 配置文件的路径作为 JVM 参数传递给每个 Kafka broker:
            -Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf
      3. 参考 这里 的描述, 在 server.properties 配置 SASL 端口和 SASL 机制. 例如:
        listeners=SASL_SSL://host.name:portsecurity.inter.broker.protocol=SASL_SSLsasl.mechanism.inter.broker.protocol=SCRAM-SHA-256 (or SCRAM-SHA-512)sasl.enabled.mechanisms=SCRAM-SHA-256 (or SCRAM-SHA-512)
    3. 配置 Kafka Client

      To configure SASL authentication on the clients: 在客户端配置 SASL 认证:
      1. 在每个客户端的 producer.properties 或者 consumer.properties 文件中配置 JAAS 配置项. 登录模块描述了像生产者和消费者这样的客户端如何连接到 Kafka Broker. 下面是一个 SCRAM 机制的客户端的配置示例:
        sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \    username="alice" \    password="alice-secret";

        usernamepassword 选项被客户端用于配置客户端连接的用户信息. 在这个例子中, 客户端作为 alice 用户连接到 broker. 通过在 sasl.jaas.config 中指定不同的用户名和密码, 在一个 JVM 内不同的客户端可以根据不同的用户连接.

        客户端的 JAAS 配置也可以像 broker 这里 描述的一样, 指定为一个 JVM 参数. 客户端使用命名为 KafkaClient 的登录部分. 此选项仅允许来自 JVM 的所有客户端连接中的一个用户.

      2. 在 producer.properties 或者 consumer.properties 中配置下面这些属性:
        security.protocol=SASL_SSLsasl.mechanism=SCRAM-SHA-256 (or SCRAM-SHA-512)
    4. SASL/SCRAM 的安全注意事项

      • Kafka 中 SASL/SCRAM 的默认实现在 Zookeeper 中保存 SCRAM 证书. 这个适合当 Zookeeper 是安全并且是在私有网络时, 在生产环境安装.
      • Kafka 只支持强散列函数 SHA-256 和 SHA-512, 和最小迭代数为4096. 如果 Zookeeper 安全性收到威胁, 强散列函数结合强密码, 高迭代次数可以防止暴力攻击.
      • SCRAM 应只使用 TLS 加密, 防止 SCRAM 交换时的中途拦截. 如果 Zookeeper 受到威胁, 这可以防止字典或者暴力攻击, 和防止伪装模拟.
      • 当 Zookeeper 不安全是, SASL/SCRAM 的默认实现可以在安装时使用自定义的登录模块重写. 更多细节查看 这里.
      • 了解安全注意事项的更多细节, 参考 RFC 5802.
  6. Enabling multiple SASL mechanisms in a broker(broker 节点上启用多个 SASL 机制 )

    1. 在JAAS配置文件的KafkaServer 部分中指定所有启用机制的登录模块的配置。例如:
          KafkaServer {        com.sun.security.auth.module.Krb5LoginModule required        useKeyTab=true        storeKey=true        keyTab="/etc/security/keytabs/kafka_server.keytab"        principal="kafka/kafka1.hostname.com@EXAMPLE.COM";
           org.apache.kafka.common.security.plain.PlainLoginModule required        username="admin"        password="admin-secret"        user_admin="admin-secret"        user_alice="alice-secret";    };
    2. 在 server.properties 配置文件中启用 SASL 机制:
          sasl.enabled.mechanisms=GSSAPI,PLAIN,SCRAM-SHA-256,SCRAM-SHA-512
    3. 如果需要,可以在 server.properties 中指定 SASL 安全协议和 broker 间的通信机制:
      security.inter.broker.protocol=SASL_PLAINTEXT (or SASL_SSL)sasl.mechanism.inter.broker.protocol=GSSAPI (or one of the other enabled mechanisms)
    4. 遵循 GSSAPI (Kerberos)、 PLAIN 和 SCRAM 特定的步骤来配置启用 SASL 机制。
  7. Modifying SASL mechanism in a Running Cluster(在运行的集群里修改 SASL 机制)

    按照下面的步骤可以修改正在运行中的集群的 SASL 机制:

    1. 为了给每个 broker 启用新的 SASL 机制,需要在 server.properties 中添加 sasl.enabled.mechanisms 配置。更新 这里描述的两种机制到JAAS配置文件。 依次更新每个集群节点
    2. 使用新机制重新启动客户端。
    3. 如果有必要,可以在 server.properties 文件中指定新的sasl.mechanism.inter.broker.protocol的配置,来修改 broker 间的通信机制。然后再次依次的更新集群。
    4. 如果有必要,可以从 server.properties 文件中的sasl.enabled.mechanisms 配置中和 JAAS 配置文件中删除旧的机制条目,来删除旧的机制。 然后再次依次的更新集群。