如何通过 terraform 使用服务帐户创建 google cloud pubsub pull 订阅?

Posted

技术标签:

【中文标题】如何通过 terraform 使用服务帐户创建 google cloud pubsub pull 订阅?【英文标题】:How to create a google cloud pubsub pull subscriptions with service account by terraform? 【发布时间】:2021-10-19 02:49:34 【问题描述】:

google_pubsub_subscription 的 terraform 文档中,它提到在 push_configuration 下有一个 oidc_token 属性允许推送订阅使用服务帐户,但没有提及如何使用服务帐户进行拉取订阅

在创建pull pubsub 订阅期间如何显式设置要使用的服务帐户?

我尝试添加 oidc_token 块,但它没有工作,因为它不希望直接使用该块。

场景:

    我有一个服务帐户,可以访问 Project_A 中的 pubsub 主题(以及附加订阅的必要权限) 我想在 terraform 的 Project_B 中创建对这些主题的订阅。 我需要在 terraform 中明确使用此服务帐户,这样我就可以在 Project_B 上创建对 Project_A 主题的订阅

google_cloudfunctions_function 资源例如,具有名为 service_account_email 的字段,用于设置服务帐户。但是documentation 中没有 google_pubsub_subscription 资源,用于拉取订阅

【问题讨论】:

【参考方案1】:

我正在添加另一个答案,因为在不同的 cmets 之后问题发生了很大变化。

这是解决方案假设主题topic-sof 已在与订阅项目不同的项目中创建。

    我在订阅项目上创建了一个服务帐户 (SA),我将其命名为 ***-playground-sa,并仅赋予它 Pub/Sub Editor 角色,如下面的屏幕截图所示。

    我在下面的屏幕截图中显示了主题 topic-sofPub/Sub Subscriber 角色。 如果您不执行此步骤:您将在 terraform apply 时收到此错误

 Error: Error creating Subscription: googleapi: Error 403: User not authorized to perform this action

当然,我与对两个项目都具有足够权限的用户进行了角色分配的前 2 步

    我为我的 SA 创建了一个 json 密钥文件并在 /path/to/my/key/***-playground-sa.json 下下载

    我使用身份验证为我的 SA

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key/***-playground-sa.json

所以它可以被 terraform 用来创建订阅。

    这是用于创建订阅的 terraform 配置
variable "subscription_project" 
  type = string
  default = "<YOUR_SUBSCRIPTION_PROJECT>"


variable "topic_project" 
  type = string
  default = "<YOUR_TOPIC_PROJECT>"


resource "google_pubsub_subscription" "pull-subscription-of-topic-in-another-project" 
  project = var.subscription_project
  name  = "pull-subscription-of-topic-in-another-project"
  topic = "projects/$var.topic_project/topics/topic-sof"

    运行 (apply) 我的 terraform,订阅 pull-subscription-of-topic-in-another-project 已创建并附加到另一个项目中的主题 topic-sof

    我使用网络用户界面向topic-sof 发布了一条消息。

    由于第 4 步,我仍然以 ***-playground-sa 身份验证,我提取了消息(在我的 treminal 中使用 gcloud)等收到消息:

总结:在您的 terraform 配置中没有为此要求指定服务帐户。服务帐户及其密钥设置在 terraform 之外(步骤 1 到 4),以便可以对 terraform 进程进行身份验证和授权以创建配置的资源(在我们的例子中是订阅)。 除了在第 4 步中使用服务帐户密钥之外,出于安全考虑,这是一种不好的做法。另一种方法是使用

gcloud auth application-default login

这将使您可以设置所选用户的默认凭据。鉴于该用户具有我为 SA 设置的角色。

【讨论】:

【参考方案2】:

实际上,服务帐户 (service_account_email) 将在 oidc_token 部分中指定(您必须在文档中进一步说明:)

下面是带有服务帐户和受众(可选)的推送子的工作示例

variable "project" 
  type = string
  default = "<YOUR_PROJECT_ID>"


resource "google_pubsub_topic" "example" 
  project = var.project
  name = "example-topic"


resource "google_pubsub_subscription" "example" 
  project = var.project
  name  = "example-push-subscription-with-auth"
  topic = google_pubsub_topic.example.name

  push_config 
    push_endpoint = "https://example.com/push"
    oidc_token 
      service_account_email = "$var.project@appspot.gserviceaccount.com"
      audience = "https://example.com/push"
    

  

【讨论】:

是的,但它适用于 push_config,它适用于推送订阅,对吗?这将是一个不单独接受 oidc_token 的 pull 订阅。 拉取订阅创建不使用服务帐户等身份。这是您的订阅者的责任,从订阅中提取消息以持有具有适当授权的身份,以便能够提取消息。在推送订阅的情况下,您可以选择提供一个服务帐户,以便在需要身份验证时能够推送并与端点交互。 我创建了一个服务帐户来访问另一个项目的 pubsub 主题,现在使用该服务帐户我想在我的项目中创建订阅。有了这个目标,(来自另一个项目的主题,我可以使用服务帐户访问,需要在我的项目上创建拉订阅)我需要在 terraform 中使用服务帐户,对吗? 好的,所以您正在谈论您使用 terraform 在您的项目中创建新的拉取订阅但附加到另一个项目中已经存在的主题的服务帐户。如果我理解得很好,您需要执行以下步骤: 1. 将pubsub.subscriptions.create 权限或roles/pubsub.editor 角色授予订阅项目的terraform 服务帐户。 2. 在请求的主题上将pubsub.topics.attachSubscriptionpermission 或roles/pubsub.subscriber 角色分配给terraform 服务帐户 有关所需权限/角色的更多详细信息,您可以查看此link)有关如何将服务帐户与 terraform 一起使用的更多详细信息,您可以查看此link

以上是关于如何通过 terraform 使用服务帐户创建 google cloud pubsub pull 订阅?的主要内容,如果未能解决你的问题,请参考以下文章

使用 terraform 如何创建一个跨多个项目使用的服务帐户?

如何在 terraform 中正确创建具有角色的 gcp 服务帐户

如何使用 Terraform 在 GKE 中设置非默认服务帐户?

terraform GCE 服务帐户节

如何使用 Terraform 将文件从本地计算机复制到存储帐户

如何使用 terraform 创建具有访问权限和密钥的 AWS IAM 服务账户