Терраформируйте gcloud

# #google-cloud-platform #terraform #google-cloud-pubsub #terraform-provider-gcp

Вопрос:

У меня есть следующая настройка в облаке Google:

  • приложение «генератор», которое публикует сообщения в теме Google Cloud PubSub.
  • приложение «рабочий», которое использует уникальное сообщение.
  • любые недопустимые сообщения PubSub должны заканчиваться в теме «мертвая буква».

В этой теме должна быть тема «мертвая буква», в которой заканчиваются недопустимые сообщения. Однако всякий раз, когда я настраиваю это с помощью Terraform, облачная консоль Google упоминает, что у меня нет ролей «подписчик» и «издатель», прикрепленных к моей учетной записи службы project pubsub:

введите описание изображения здесь

У меня есть следующая конфигурация терраформы, которая кажется правильной AFAIK:

 resource "google_project_service_identity" "pubsub_sa" {
    provider = google-beta
    
    project = var.project_id
    service = "pubsub.googleapis.com"
}

/* ... topic and dead-letter topic config here ... */

data "google_iam_policy" "project_pubsub_publishers" {
    binding {
        role = "roles/pubsub.publisher"
        members = [
            "serviceAccount:${google_service_account.project_generator_serviceaccount.email}",
            "serviceAccount:${google_service_account.project_worker_serviceaccount.email}",
            "serviceAccount:${google_project_service_identity.pubsub_sa.email}",
        ]
    }
}

resource "google_pubsub_topic_iam_policy" "project_request_publishers" {
    project  = var.project_id
    topic = google_pubsub_topic.generator_request_pubsub.name
    policy_data = data.google_iam_policy.project_pubsub_publishers.policy_data
}

data "google_iam_policy" "project_pubsub_subscribers" {
    binding {
        role = "roles/pubsub.subscriber"
        members = [
            "serviceAccount:${google_service_account.project_generator_serviceaccount.email}",
            "serviceAccount:${google_service_account.project_worker_serviceaccount.email}",
            "serviceAccount:${google_project_service_identity.pubsub_sa.email}",
        ]
    }
}

resource "google_pubsub_topic_iam_policy" "project_request_subscribers" {
    topic = google_pubsub_topic.generator_request_pubsub.name
    project  = var.project_id
    policy_data = data.google_iam_policy.project_pubsub_subscribers.policy_data
}
 

Нажав «Добавить» в веб-интерфейсе, а затем выполнив terraform plan следующие изменения:

 Terraform will perform the following actions:

  # module.gcloud.google_pubsub_topic_iam_policy.project_invalid_request_publishers will be updated in-place
  ~ resource "google_pubsub_topic_iam_policy" "project_invalid_request_publishers" {
        id          = "projects/MY-GCLOUD-PROJECTID/topics/generator-request-pubsub-invalid"
      ~ policy_data = jsonencode(
          ~ {
              ~ bindings = [
                  ~ {
                      ~ members = [
                            "serviceAccount:cicd-generator-sa@MY-GCLOUD-PROJECTID.iam.gserviceaccount.com",
                            "serviceAccount:cicd-worker-sa@MY-GCLOUD-PROJECTID.iam.gserviceaccount.com",
                            "serviceAccount:service-251572179467@gcp-sa-pubsub.iam.gserviceaccount.com",
                        ]
                        # (1 unchanged element hidden)
                    },
                  - {
                      - members = [
                          - "serviceAccount:cicd-generator-sa@MY-GCLOUD-PROJECTID.iam.gserviceaccount.com",
                          - "serviceAccount:cicd-worker-sa@MY-GCLOUD-PROJECTID.iam.gserviceaccount.com",
                          - "serviceAccount:service-251572179467@gcp-sa-pubsub.iam.gserviceaccount.com",
                        ]
                      - role    = "roles/pubsub.subscriber"
                    },
                ]
            }
        )
        # (3 unchanged attributes hidden)
    }

  # module.gcloud.google_pubsub_topic_iam_policy.project_invalid_request_subscribers will be updated in-place
  ~ resource "google_pubsub_topic_iam_policy" "project_invalid_request_subscribers" {
        id          = "projects/MY-GCLOUD-PROJECTID/topics/generator-request-pubsub-invalid"
      ~ policy_data = jsonencode(
          ~ {
              ~ bindings = [
                  - {
                      - members = [
                          - "serviceAccount:service-251572179467@gcp-sa-pubsub.iam.gserviceaccount.com",
                        ]
                      - role    = "roles/pubsub.publisher"
                    },
                    {
                        members = [
                            "serviceAccount:cicd-generator-sa@MY-GCLOUD-PROJECTID.iam.gserviceaccount.com",
                            "serviceAccount:cicd-worker-sa@MY-GCLOUD-PROJECTID.iam.gserviceaccount.com",
                            "serviceAccount:service-251572179467@gcp-sa-pubsub.iam.gserviceaccount.com",
                        ]
                        role    = "roles/pubsub.subscriber"
                    },
                ]
            }
        )
        # (3 unchanged attributes hidden)
    }

  # module.gcloud.google_pubsub_topic_iam_policy.project_request_subscribers will be updated in-place
  ~ resource "google_pubsub_topic_iam_policy" "project_request_subscribers" {
        id          = "projects/MY-GCLOUD-PROJECTID/topics/generator-request-pubsub"
      ~ policy_data = jsonencode(
          ~ {
              ~ bindings = [
                  ~ {
                      ~ role    = "roles/pubsub.publisher" -> "roles/pubsub.subscriber"
                        # (1 unchanged element hidden)
                    },
                ]
            }
        )
        # (3 unchanged attributes hidden)
    }
 

Но я не уверен, что я здесь делаю не так. Есть какие-нибудь идеи?

Ответ №1:

В соответствии с документацией, кажется, что вам нужно сначала фактически настроить конфигурацию для «мертвой темы» в GCP.

Установка темы с мертвой буквой

В котором (среди некоторой другой информации) говорится, что:

Чтобы создать подписку и задать тему с мертвой буквой, используйте команду создания подписок gcloud pubsub:

 gcloud pubsub subscriptions create subscription-id 
  --topic=topic-id 
  --dead-letter-topic=dead-letter-topic-id 
  [--max-delivery-attempts=max-delivery-attempts] 
  [--dead-letter-topic-project=dead-letter-topic-project]
 

Чтобы обновить подписку и задать тему с мертвой буквой, используйте команду обновления подписок gcloud pubsub:

 gcloud pubsub subscriptions update subscription-id 
  --dead-letter-topic=dead-letter-topic-id 
  [--max-delivery-attempts=max-delivery-attempts] 
  [--dead-letter-topic-project=dead-letter-topic-project]
 

Предоставление разрешений на пересылку
Чтобы пересылать недоставленные сообщения в тему с мертвыми буквами, Pub/Sub должен иметь разрешение на выполнение следующих действий:

Публикуйте сообщения в этой теме.
Подтвердите сообщения, что удалит их из подписки.

Pub/Sub создает и поддерживает учетную запись службы для каждого проекта: service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com . Вы можете предоставить разрешения на пересылку, назначив этой учетной записи службы роли издателя и подписчика. Если вы настроили подписку с помощью Облачной консоли, роли предоставляются автоматически.

Назначение Pub/Sub роли издателя
Чтобы предоставить Pub/Sub разрешение на публикацию сообщений в теме с мертвой буквой, выполните следующую команду:

 PUBSUB_SERVICE_ACCOUNT="service-${project-number}@gcp-sa-pubsub.iam.gserviceaccount.com"

gcloud pubsub topics add-iam-policy-binding dead-letter-topic-id 
    --member="serviceAccount:$PUBSUB_SERVICE_ACCOUNT"
    --role="roles/pubsub.publisher"
 

Назначение Pub/Sub роли подписчика
Чтобы предоставить Pub/Sub разрешение на подтверждение пересылаемых недоставленных сообщений, выполните следующую команду:

 PUBSUB_SERVICE_ACCOUNT="service-${project-number}@gcp-sa-pubsub.iam.gserviceaccount.com"

gcloud pubsub subscriptions add-iam-policy-binding subscription-id 
    --member="serviceAccount:$PUBSUB_SERVICE_ACCOUNT"
    --role="roles/pubsub.subscriber"
 

Надеюсь, это будет полезно для вас.
С уважением.

Комментарии:

1. Привет, Джейме, не уверен, как это поможет, так как мой вопрос касается конкретной формы, но спасибо, что вмешался! Интересно, что пользователь «pubsub_sa», который включен в обе роли, является учетной записью службы: « ресурс «google_project_service_identity» «pubsub_sa» { поставщик = проект google-бета = var.project_id службы = «pubsub.googleapis.com» } «

Ответ №2:

Хайме прав, вам нужно добавить эти политики IAM в

 "service-${project-number}@gcp-sa-pubsub.iam.gserviceaccount.com"
 

Это специфический sa, скрытый от основных. Вы можете найти его в консоли в разделе >IAM и установить флажок в правом верхнем углу «>включить предоставленные Google роли».

Там также необходимо добавить a google_pubsub_topic_iam_policy .

Вот рабочий пример терраформирования

 data "google_project" "current" {}

data "google_iam_policy" "publisher" {
  binding {
    role = "roles/pubsub.publisher"
    members = [
      "serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com",
    ]
  }
}
resource "google_pubsub_topic_iam_policy" "policy" {
  project = var.project
  topic = google_pubsub_topic.yourTopic.name
  policy_data = data.google_iam_policy.publisher.policy_data
}
data "google_iam_policy" "subscriber" {
  binding {
    role = "roles/pubsub.subscriber"
    members = [
      "serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com",
    ]
  }
}
resource "google_pubsub_subscription_iam_policy" "policy" {
  subscription = google_pubsub_subscription.yourSubscription.name
  policy_data  = data.google_iam_policy.subscriber.policy_data
}