使用 Kafka ACL 进行访问权限控制

本文档介绍了如何在 Google Cloud Managed Service for Apache Kafka 中使用 Apache Kafka 访问权限控制列表 (ACL) 进行访问权限控制。

Apache Kafka ACL 可在 Kafka 集群内提供精细的访问权限控制。Managed Service for Apache Kafka 可实现开箱即用的 StandardAuthorizer,该功能可将 ACL 存储在基于 KRaft 的 Kafka 集群元数据中。

  • 这些 ACL 可控制哪些经过身份验证的用户可以对特定 Kafka 资源执行特定操作,例如在主题上生成或使用消息。

  • 这些 ACL 可用于控制使用标准 Apache Kafka 客户端与集群的互动,这些客户端仅在初始连接时接受集群级 IAM 检查。如需了解详情,请参阅使用 IAM 进行访问权限控制

Kafka ACL 访问权限控制的工作方式

客户端与集群内的 Kafka 标准 ACL 授权方进行交互。授权方会评估相关的 Apache Kafka ACL,以授权正文请求的特定操作,例如向主题生成消息或从群组中消费消息。用于 ACL 检查的主账号派生自以下身份验证方法之一:

  • SASL:IAM 主账号,例如服务账号电子邮件地址。

  • mTLS:客户端证书中的标识名 (DN),可能会通过正文映射规则进行转换。

为实现全面的安全性,您必须配置以下内容:

  • 用于管理访问权限的 IAM 权限。如需了解详情,请参阅使用 IAM 进行访问权限控制

  • 用于从开源 Apache Kafka 客户端进行集群内数据访问和操作的 Kafka ACL,与身份验证方法无关。

Apache Kafka ACL 的使用

Apache Kafka ACL 绑定采用以下格式:


Principal P is [Allowed/Denied] Operation O From Host H on any resource matching Resource Pattern RP.

以下是有关此格式的重要信息:

  • 正文(P):获得授权的用户身份。该值以 User: 为前缀。

    • 对于 SASL 身份验证,这是 IAM 主账号,例如 User:my-service-account@my-project.iam.gserviceaccount.com

    • 对于 mTLS 身份验证,这是客户端证书中的可分辨名称 (DN),例如 User:CN=my-client,OU=my-org-unit。 确切格式取决于证书的主题。正文映射规则可以转换此值。

  • 权限类型(允许/拒绝):ACL 绑定是允许还是拒绝访问。拒绝绑定优先。

  • 操作(O):执行的操作,例如读取、写入或创建。 如需了解哪些操作适用于各种 Kafka 协议的哪些资源,请参阅 Apache Kafka 文档中的协议上的操作和资源

  • 主机(H):发起请求的机器。由于 Managed Service for Apache Kafka 会转换客户端网络地址,因此不支持使用 '*' 以外的主机。

  • 资源模式(RP):用于匹配特定资源的模式。资源模式由资源类型、资源名称和模式类型(LITERALPREFIXED)组成。

默认访问权限

Managed Service for Apache Kafka 集群在运行时,Apache Kafka 属性 allow.everyone.if.no.acl.found 设置为 true。Kafka ACL 的存在与否直接决定了对资源的访问权限级别:

  • 如果未为特定资源(例如主题)定义任何 Kafka ACL,则所有经过身份验证的正文都会被授予对该资源的访问权限。此配置可让 Managed Service for Apache Kafka 集群立即运行,无需配置 ACL。

  • 只要您为相应资源定义了任何 Kafka ACL,访问权限就会受到限制。只有在 Kafka ACL 中使用 ALLOW 条目明确授予权限的主账号才能访问匹配的资源(除非被 DENY 条目明确阻止)。

Managed Service for Apache Kafka 会向其服务代理授予对集群的管理访问权限。此访问权限允许服务代理执行 Managed Service for Apache Kafka API 请求的操作,而无需考虑集群中配置的其他 ACL。Managed Service for Apache Kafka 通过修改 StandardAuthorizer 实现来完成此操作。此修改授予服务代理与超级用户类似的权限,但读写操作除外。您无法更改此配置。

Kafka 主账号

Managed Service for Apache Kafka 集群的 Kafka 主账号使用 Kafka StandardAuthorizer 前缀 "User:" 指定。

  • 对于 SASL/IAM:正文是Google Cloud 账号。例如,如需向服务账号 test-kafka-client@test-project.iam.gserviceaccount.com 授予访问权限,请使用 Kafka 主账号 "User:test-kafka-client@test-project.iam.gserviceaccount.com"。Kafka ACL 主账号必须指定用户、服务账号或单个 IAM 主账号,但不能指定群组或主账号集。Kafka ACL 不支持为 Google Cloud 正文解析群组成员资格。

  • 对于 mTLS:正文派生自客户端证书的主题标识名 (DN)。例如 User:CN=client1,OU=dev,O=MyOrg,L=City,ST=State,C=US。 您可以使用 mTLS 主账号映射规则将 DN 转换为更便于用户理解的 ACL 主账号字符串。

如需创建适用于 Google 群组或主账号集所有成员的 ACL,您可以使用代理服务账号主账号和服务账号模拟:

  1. 创建服务账号以用作群组的代理。

  2. 向 Google 群组或主账号集授予服务账号的 Service Account Token Creator 角色。请参阅管理对服务账号的访问权限

  3. 为代理服务账号添加 Kafka ACL。主账号示例:User:group-proxy@test-project.iam.gserviceaccount.com

  4. 在 Kafka 客户端中使用服务账号模拟,以服务账号身份向 Kafka 进行身份验证。 Google Cloud IAM 授权单个主账号作为允许模拟代理服务账号的群组的成员。Kafka 会根据集群中的现有 ACL 授权代理服务账号。

针对生产方和使用方的 Kafka 操作

操作是指对资源执行的操作。对于每种资源,一个操作会映射到该资源的一个或多个 Kafka 协议请求。例如,topic 资源类型的 READ 操作会映射到 FetchOffsetCommitTxnOffsetCommit Apache Kafka 协议。

如需向主账号授予主题的生产者访问权限,请执行以下步骤:

  1. 在主题资源上,允许 WRITECREATE 操作。

  2. 如果使用交易 ID,请在交易 ID 资源上允许 WRITE 操作。

如需向主账号授予对主题的消费者访问权限,请执行以下步骤:

  1. 允许对主题资源执行 READ 操作。

  2. 在消费者群组资源上,允许 READ 操作。

如需详细了解 Kafka API 支持的对资源执行的有效操作,请参阅 Apache Kafka 文档中的协议的操作和资源

为默认拒绝行为配置 ACL

托管式 Kafka 集群配置了 allow.everyone.if.no.acl.found = true。因此,默认情况下,如果未对资源设置任何 ACL,则所有主账号都可以访问该资源。

如需配置与 IAM 中类似的 default-deny 行为,您可以先为集群中所有资源的管理员用户配置访问权限。因此,每个资源都会获得一个定义在其上的 ACL,并且 allow.everyone.if.no.acl.found 行为会被抑制。默认情况下,任何未通过 ALLOW ACL 明确允许的主账号都会被拒绝访问。

例如,如需为服务账号 clusterAdmin@test-project.iam.gserviceaccount.com 设置集群中所有资源的 ACL,请创建以下 ACL 条目。

以下 gcloud CLI 命令会向名为 clusterAdmin@test-project.iam.gserviceaccount.com 的服务账号授予对特定区域中特定 Kafka 集群的完整管理员权限 (--operation=ALL)。此权限允许服务账号从任何主机对集群执行任何操作。

gcloud managed-kafka acls add-acl-entry cluster \
    --principal=`User:clusterAdmin@test-project.iam.gserviceaccount.com` \
    --operation=ALL \
    --permission-type=ALLOW \
    --host=* \
    --cluster=CLUSTER_ID \
    --location=LOCATION

以下 gcloud CLI 命令会向名为 clusterAdmin@test-project.iam.gserviceaccount.com 的服务账号授予对特定区域中特定 Kafka 集群内所有主题的完整管理员权限 (--operation=ALL)。此权限允许服务账号从任何主机对所有主题执行任何操作。

gcloud managed-kafka acls add-acl-entry allTopics \
    --principal=`User:clusterAdmin@test-project.iam.gserviceaccount.com` \
    --operation=ALL \
    --permission-type=ALLOW \
    --host=* \
    --cluster=CLUSTER_ID \
    --location=LOCATION

以下 gcloud CLI 命令会向名为 clusterAdmin@test-project.iam.gserviceaccount.com 的服务账号授予对特定区域中特定 Kafka 集群内的所有消费者群组的完整管理员权限 (--operation=ALL)。此权限允许服务账号从任何主机对所有消费群组执行任何操作。

gcloud managed-kafka acls add-acl-entry allConsumerGroups \
    --principal=`User:clusterAdmin@test-project.iam.gserviceaccount.com` \
    --operation=ALL \
    --permission-type=ALLOW \
    --host=* \
    --cluster=CLUSTER_ID \
    --location=LOCATION

以下 gcloud CLI 命令会向名为 clusterAdmin@test-project.iam.gserviceaccount.com 的服务账号授予对特定区域中特定 Kafka 集群内的所有事务 ID 的完全管理员权限 (--operation=ALL)。此权限允许服务账号对来自任何主机的任何事务 ID 执行任何操作。

gcloud managed-kafka acls add-acl-entry allTransactionalIds \
    --principal=`User:clusterAdmin@test-project.iam.gserviceaccount.com` \
    --operation=ALL \
    --permission-type=ALLOW \
    --host=* \
    --cluster=CLUSTER_ID \
    --location=LOCATION

以下是有关命令的重要信息列表:

  • --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com':ACL 所应用的主账号。该主账号是一个Google Cloud 账号,带有 Kafka StandardAuthorizer 前缀 User:

  • --operation=all:授予的 Kafka 操作,在本例中为完全访问权限。

  • --permission-type=ALLOW:此 ACL 条目授予访问权限。

  • --host='*':主账号可以访问资源的宿主。 '*' 授予来自任何主机的访问权限。Managed Service for Apache Kafka 仅支持具有主机 '*' 的 ACL。

  • CLUSTER_ID:您的 Managed Service for Apache Kafka 集群的名称。

  • LOCATION:您的 Managed Service for Apache Kafka 集群所在的 Google Cloud 区域,例如 us-central1

配置 ACL

您可以使用 Managed Service for Apache Kafka ACL API 或开源 Apache Kafka 工具(例如 Apache Kafka 授权方 CLI kafka-acls.shAdmin Client)配置 Apache Kafka ACL。

Managed Service for Apache Kafka 会按 Kafka 资源模式整理 ACL。资源模式由以下内容定义:

  • 资源类型:集群、主题、消费群组或事务 ID

  • 模式类型:字面量或带前缀(名称以提供的字符串开头的所有资源)

  • 资源名称:ACL 条目所适用的资源名称或前缀。

Managed Service for Apache Kafka ACL 资源表示为单个 Kafka 资源模式配置的所有访问权限控制,以 ACL 条目的重复列表的形式表示。ACL 资源的名称可唯一标识 ACL 绑定的资源模式。如需了解详情,请参阅 ACL ID

您可以在 ACL 资源级别(针对资源模式的所有 ACL 条目)管理 Managed Service for Apache Kafka ACL,也可以通过为 ACL 资源模式添加和移除各个 ACL 条目来增量管理。

如需了解详情,请参阅创建托管 Kafka ACL添加托管 Kafka ACL 条目

允许从主题中读取数据

如需允许以服务账号 test-kafka-client@test-project.iam.gserviceaccount.com 运行的开源 Apache Kafka 客户端从主题 topic-name 读取数据,请使用 managed-kafka acls add-acl-entry 命令创建 Managed Service for Apache Kafka ACL 条目:

gcloud managed-kafka acls add-acl-entry topic/topic-name \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=READ \
    --permission-type=ALLOW \
    --host='*'

以下是有关该命令的重要信息:

  • topic/topic-name:指定您要授予访问权限的 Managed Service for Apache Kafka 主题。将 topic-name 替换为主题的实际名称。topic/ 前缀表示此 ACL 条目适用于特定的(字面)主题资源模式。

  • LOCATION:您的 Managed Service for Apache Kafka 集群所在的 Google Cloud 区域,例如 us-central1

  • CLUSTER_ID:您的 Managed Service for Apache Kafka 集群的名称。

  • --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com':ACL 所应用的主账号。该主账号是一个Google Cloud 账号,带有 Kafka StandardAuthorizer 前缀 User:

  • --operation=READ:要授予的 Kafka 操作,在本例中为 READ

  • --permission-type=ALLOW:表示此 ACL 条目授予访问权限。

  • --host='*':指定主账号可以访问资源的主机。'*' 授予来自任何主机的访问权限。 Managed Service for Apache Kafka 仅支持具有主机 '*' 的 ACL。

如需移除读取权限,您可以使用具有相同参数的 remove-acl-entry 命令

gcloud managed-kafka acls remove-acl-entry topic/topic-name \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=READ \
    --permission-type=ALLOW \
    --host='*'

允许写入具有共同前缀的所有主题

如需允许以服务账号 test-kafka-client@test-project.iam.gserviceaccount.com 运行的开源 Apache Kafka 客户端写入名称以 topic-prefix 为前缀的所有主题,请添加以下 Managed Kafka ACL 条目:

gcloud managed-kafka acls add-acl-entry topicPrefixed/topic-prefix \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=WRITE \
    --permission-type=ALLOW \
    --host='*'

以下是有关该命令的重要信息:

  • topicPrefixed/topic-prefix:指定您要授予访问权限的 Managed Service for Apache Kafka 资源模式。将 topic-prefix 替换为您的主题的实际前缀。topicPrefixed/ 前缀表示此 ACL 条目适用于带前缀的资源模式:与给定前缀匹配的所有主题。

  • PROJECT:您的 Managed Service for Apache Kafka 集群所在的 Google Cloud 项目的 ID。

  • LOCATION:您的 Managed Service for Apache Kafka 集群所在的 Google Cloud 区域,例如 us-central1

  • CLUSTER_ID:您的 Managed Service for Apache Kafka 集群的名称。

  • --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com':ACL 所应用的主账号。该主账号是一个Google Cloud 账号,带有 Kafka StandardAuthorizer 前缀 User:

  • --operation=WRITE:要授予的 Kafka 操作,在本例中为 WRITE

  • --permission-type=ALLOW:此 ACL 条目授予访问权限。

  • --host='*':主账号可以访问资源的宿主。 '*' 授予来自任何主机的访问权限。Managed Service for Apache Kafka 仅支持具有主机 '*' 的 ACL。

如需移除此服务账号的写入权限,请移除相应的 ACL 条目:

gcloud managed-kafka acls remove-acl-entry topicPrefixed/topic-prefix \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=WRITE \
    --permission-type=ALLOW \
    --host='*'

拒绝修改所有主题

为防止以服务账号 test-kafka-client@test-project.iam.gserviceaccount.com 运行的开源 Apache Kafka 客户端修改集群中的所有主题,您可以创建一个 Managed Service for Apache Kafka ACL 资源,其中包含一个 AclEntry 资源列表,以拒绝针对所有主题执行 ALTERALTER_CONFIGSDELETE 操作。此方法在单个配置中定义所需的状态。

或者,您也可以使用 gcloud managed-kafka acls add-acl-entry 命令以命令式方式添加三个单独的 ACL 条目,从而实现相同的结果。此方法涉及运行命令来拒绝访问每项操作 ALTERALTER_CONFIGSDELETE,如下所示:

gcloud managed-kafka acls add-acl-entry allTopics \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=ALTER \
    --permission-type=DENY \
    --host='*'
gcloud managed-kafka acls add-acl-entry allTopics \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=ALTER_CONFIGS \
    --permission-type=DENY \
    --host='*'
gcloud managed-kafka acls add-acl-entry allTopics \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=DELETE \
    --permission-type=DENY \
    --host='*'

以下信息适用于每个 add-acl-entry 命令:

  • allTopics:指定此 ACL 适用于 Managed Service for Apache Kafka 集群中的所有主题。

  • LOCATION:您的 Managed Service for Apache Kafka 集群所在的 Google Cloud 区域,例如 us-central1

  • CLUSTER_ID:您的 Managed Service for Apache Kafka 集群的名称。

  • --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com':指定 ACL 所应用的主账号。该主账号是一个Google Cloud 账号,带有 Kafka StandardAuthorizer 前缀 User:

  • --operation:指定被拒绝的 Kafka 操作:

    • ALTER:包括更改分区数或复制因子等操作。

    • ALTER_CONFIGS:包括修改主题级配置。

    • DELETE:包括删除主题。

  • --permission-type=DENY:表示这些 ACL 条目会阻止对指定操作的访问。

  • --host='*':指定无论请求来自哪个主机,此拒绝都适用。Managed Service for Apache Kafka 仅支持具有主机 '*' 的 ACL。

如需移除这些限制,请针对每个添加的条目使用 remove-acl-entry 命令,并使用相同的参数。例如,如需重新允许删除主题,请执行以下操作:

gcloud managed-kafka acls remove-acl-entry allTopics \
    --cluster=CLUSTER_ID \
    --location=LOCATION
    --principal='User:test-kafka-client@test-project.iam.gserviceaccount.com' \
    --operation=DELETE \
    --permission-type=DENY \
    --host='*'

排查 ACL 问题

Apache Kafka 标准授权方默认会在授权被拒绝时写入审核日志。如果您收到 Kafka 授权错误,可以搜索集群日志中的 StandardAuthorizerData logAuditMessage,确认被拒绝的主账号、资源和操作。

例如,以下是一个集群日志示例。

org.apache.kafka.metadata.authorizer.StandardAuthorizerData logAuditMessage\n
INFO: Principal = User:556291496362-compute@developer.iam.gserviceaccount.com is
Denied operation = DESCRIBE from host = 172.16.0.20 on resource = Topic:LITERAL:t1
for request = Metadata with resourceRefCount = 1 based on rule DefaultDeny

后续步骤

Apache Kafka® 是 Apache Software Foundation 或其关联公司在美国和/或其他国家/地区的注册商标。