亚马逊AWS官方博客

如何通过互联网安全地访问Amazon Managed Streaming for Apache Kafka (Amazon MSK) 集群(一)

Amazon MSK 简介

Amazon MSK 是一项完全托管式的 Apache Kafka 和 Kafka Connect 服务,让用户可以轻松构建并运行使用 Apache Kafka 作为数据存储或者使用Apache Kafka 来处理流数据的应用程序。Amazon MSK 与 Apache Kafka 完全兼容,用户完全可以放心将现有的 Apache Kafka 工作负载快速迁移到 Amazon MSK,或从头开始构建新的工作负载。借助 Amazon MSK,用户可以将更多时间和精力用于应用程序创新,并花费更少的时间管理集群。

 

公开访问Public Access 介绍

在业务全球化的今天,各类业务服务或游戏服务器可能遍布全球各地,而数据往往都会通过Kafka服务收集汇总到一起进行分析计算,以游戏公司为例:游戏的中心服务器或平台服可能部署在一个中心区域做数据的汇总,而对战服务器和分区域的大厅服务器这些产生大量日志的模块,可能部署在全球各地离玩家较近的区域。这样的技术架构常有收集和汇总日志的需求,往往日志会消耗大量带宽,如果将日志业务运行在专线或者VPN上,可能会导致关键内网通讯业务收到影响,而且增加了专线和VPN的成本。因此日志收集服务常会使用公网进行传输,而在传输过程中通过协议和端到端加密保证数据安全性。 默认情况下,Amazon MSK集群的设计不能通过公共互联网到达。因此,从本地网络、自建IDC或外部云环境中以安全和灵活的方式访问MSK是困难的。这阻碍了MSK在混合或多云设置中的部署,并使业务架构整合计划变得复杂。

为此,Amazon MSK新提供了通过 Internet 互联网安全连接到 Amazon MSK 集群的选项。通过启用Public Access选项,私有 Amazon Virtual Private Cloud(VPC)外部的授权客户端可以通过安全加密的通道进行数据传入和传出到对应的 Amazon MSK 集群。用户可以免费为 MSK 集群启用Public Access,集群传入和传出将按标准亚马逊云科技数据传输成本计费。

在创建Amazon MSK集群后,用户只需简单修改配置选项就可以启用Public Access功能,并且该功能在所有提供 Amazon MSK 的亚马逊云科技区域均受支持。因为是开启了公开对外访问,为了进一步加强数据安全性,Public Access选项要求客户端使用 TLS 加密流量,并使用 IAM 访问控制、SASL/SCRAM 或者mTLS 身份验证向 MSK 集群进行身份验证。

本文讲介绍三种访问启用Public Access选项的MSK集群的第一种方式 – 通过IAM访问控制来完成,后面会陆续更新SASL/SCRAM 以及mTLS 身份验证的方法。

通过IAM访问控制来访问MSK集群的架构图如下所示。其中,区别于在VPC内网访问MSK集群可以通过EC2的IAM角色来获取短期安全凭证,外网访问的客户端通过配置Access Key和Secret Access Key来进行访问。

接下来,我们通过以下步骤来完成Amazon MSK集群的公开访问配置和验证:

  1. 创建Amazon MSK集群;
  2. 开启Public Access权限;
  3. 创建公开访问的客户端;
  4. 配置IAM访问控制连接Amazon MSK集群;
  5. 创建并配置IAM授权策略;
  6. 验证公开访问。

 

创建Amazon MSK集群

Amazon MSK 允许用户选择 Apache Kafka 2.6.0 或更高版本的 MSK 集群开启Public Access选项。亚马逊云科技出于数据安全的角度考虑,用户无法在创建 MSK 集群时直接启用Public Access,用户可以更新在创建集群后开启该选项以使其可以被公开访问。这里以us-east-1美东1区域为例进行演示。

要启用对集群的Public Access选项,与集群关联的子网必须是公有子网Public Subnet,这意味着子网必须具有连接 Internet 网关的关联路由表。有关如何创建和关联 Internet 网关的更多信息,可以参考Amazon VPC 用户指南

确保选择的安全规则组配置了合适的入站规则:

对于公开访问的MSK集群,可以参考以下集群端口信息:

  • 如果是通过TLS 加密与Broker进行通信,需要通过9194 端口公开访问;
  • 如果是通过 SASL/SCRAM 与Broker进行通信,需要通过9196 端口公开访问;
  • 如果是通过IAM 访问控制与Broker进行通信,需要通过9198 端口公开访问;
  • 如果是通过TLS 加密与Apache Zookeeper进行通信,需要通过2182 端口公开访问。

接下来是安全设置,要想使用Public Access选项,集群必须关闭Unauthenticated access未经身份验证的访问控制选项,并且这里在示例中我们开启IAM访问控制的选项。

如果开启Public Access选项,集群内加密默认是必选项;另外,客户端和Broker之间的明文流量也会被关闭,必须使用TLS加密的方式进行。

保持其他参数为默认选项,然后创建MSK集群。

开启Public Access权限

在集群创建完成后,在集群的网络设置里选择配置公开访问。

勾选开启,同时注意这次再次提醒需要确保集群的子网具有连接 Internet 网关的关联路由表,并且安全规则组限制了访问对象来源。

创建公开访问的客户端

在等待集群公开访问配置生效的过程中,我们来创建一个示例Kafka客户端,来模拟Internet访问请求。此处参照文档创建客户端实例,并根据文档创建Topic来安装Java环境。

配置IAM访问控制连接Amazon MSK集群

以下操作是在客户端实例上进行。在示例中,我们使用JVM Truststore与MSK集群进行通信,所以我们需要对应的Truststore文件,这里在客户端实例上将Java中的证书复制到/tmp目录下,根据用户不同的Java安装方式和路径,这里的文件路径需要进行适当的替换。

cp /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-0.amzn2.x86_64/jre/lib/security/cacerts /tmp/kafka.client.truststore.jks

示例中我们以Kafka自带的脚本工具为例演示如何进行配置,Java或者其他应用程序可以以此作为参考。切换到Kafka文件夹中,并创建名为client.properties的配置文件,复制以下内容到配置文件中:

ssl.truststore.location=/tmp/kafka.client.truststore.jks
security.protocol=SASL_SSL
sasl.mechanism=AWS_MSK_IAM
sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;
sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler

然后,下载最新的JAR文件aws-msk-iam-auth,这里测试的版本是1.1.3。该库提供了一种新的Simple Authentication and Security Layer(SASL)机制AWS_MSK_IAM,使得Amazon MSK开发者能够通过基于JVM的Apache Kafka客户端使用IAM对Amazon MSK集群进行认证和授权,更多信息请参考对应的GitHub项目

保持在Kafka文件夹中,下载文件到libs目录中。

wget https://github.com/aws/aws-msk-iam-auth/releases/download/v1.1.3/aws-msk-iam-auth-1.1.3-all.jar -P libs/

如果使用的是Java应用程序,可以在Maven中参考以下内容进行配置:

<dependency>
    <groupId>software.amazon.msk</groupId>
    <artifactId>aws-msk-iam-auth</artifactId>
    <version>1.1.3</version>
</dependency>


创建并配置
IAM授权策略

接下来,我们将创建可以访问MSK集群的IAM策略,并附加到与客户端对应的 IAM 用户。可以参考以下示例策略,并替换对应的账号和集群信息。更多有关策略的配置,请参考文档MSK IAM 访问控制

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:Connect",
                "kafka-cluster:AlterCluster",
                "kafka-cluster:DescribeCluster"
            ],
            "Resource": [
                "arn:aws:kafka:us-east-1:<account-id>:cluster/<cluster-name>/<cluster-uuid>"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:*Topic*",
                "kafka-cluster:WriteData",
                "kafka-cluster:ReadData"
            ],
            "Resource": [
                "arn:aws:kafka:us-east-1:<account-id>:topic/<cluster-name>/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:AlterGroup",
                "kafka-cluster:DescribeGroup"
            ],
            "Resource": [
                "arn:aws:kafka:us-east-1:<account-id>:group/<cluster-name>/*"
            ]
        }
    ]
}

然后,我们在客户端实例上通过环境变量的方式配置IAM用户的AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY,并替换对应的密钥信息:

export AWS_ACCESS_KEY_ID=<ACCESS KEY>
export AWS_SECRET_ACCESS_KEY=<SECRET ACCESS KEY>
export AWS_DEFAULT_REGION=us-east-1


验证公开访问

首先,查看MSK集群的bootstrap连接信息:

*注:公开访问启用成功后,可以到EC2控制台查看MSK集群配置的网卡信息,可以看到MSK集群对网卡进行了公网IP对应集群的域名,如下所示:

*注:出于安全原因,Amazon MSK不允许公开访问Apache Zookeeper节点,因此这里创建topic的时候需要VPC内网访问。或者,用户可以配置auto.create.topics.enable集群选项,设置为true(默认为false),这样可以启用在服务器上自动创建topic,更多信息可以参考文档自定义MSK集群配置

然后,通过以下参考命令生产示例消息:

bin/kafka-console-producer.sh --broker-list BootstrapBroker-String --topic ExampleTopic --producer.config client.properties

如下图所示:

再同时打开另一个客户端连接窗口,通过以下参考命令消费示例消息:

bin/kafka-console-consumer.sh --bootstrap-server BootstrapBroker-String --topic ExampleTopic --consumer.config client.properties

如下图所示:

以上,验证成功。

 

小结

本文首先介绍了需要公开访问Amazon MSK集群的应用场景,并手把手地说明了如何配置Amazon MSK集群的Public Access选项,以及通过IAM访问认证的方式来安全地访问集群。之后,我们会通过另外的博客来介绍公开访问Amazon MSK集群的其他两种模式:SASL/SCRAM 和mTLS 身份验证,敬请期待!

参考资料

https://docs.aws.amazon.com/msk/latest/developerguide/public-access.html

https://docs.aws.amazon.com/msk/latest/developerguide/msk-update-security.html

https://docs.aws.amazon.com/msk/latest/developerguide/iam-access-control.html

https://docs.aws.amazon.com/msk/latest/developerguide/msk-working-with-encryption.html

https://aws.amazon.com/cn/blogs/big-data/securing-apache-kafka-is-easy-and-familiar-with-iam-access-control-for-amazon-msk/

本篇作者

史天

亚马逊云科技资深解决方案架构师。拥有丰富的云计算、数据分析和机器学习经验,目前致力于数据科学、机器学习、无服务器等领域的研究和实践。译有《机器学习即服务》《基于Kubernetes的DevOps实践》《Kubernetes微服务实战》《Prometheus监控实战》《云原生时代的CoreDNS学习指南》等。

本篇作者

齐海澎

齐海澎,亚马逊云科技资深解决方案架构师,亚马逊云科技游戏技术社区中国区负责人,有多年Devops经验,擅长各种类型游戏架构与运维解决方案,致力于Amazon GameTech的推广,在Gamelift等游戏服务上有丰富的实践经验。