ayyayyekokojambo
ayyayyekokojambo

Reputation: 1245

How to create a google cloud pubsub pull subscriptions with service account by terraform?

In the terraform documentation for google_pubsub_subscription, it mentions having a oidc_token property under push_configuration allows push-subscriptions to utilise service account, but has no mention on how to use service account for pull subscriptions.

How can explicitly set the service account to be used during the creation of pull pubsub subscriptions?

I tried adding oidc_token block, but it did not worked as it does not expect that block directly.

Scenario:

  1. I have a service account that has access to pubsub topics (and necessary permissions to attach subscriptions to it) in Project_A
  2. I want to create subscriptions to those topics in Project_B in terraform.
  3. I need to explicitly use this service account in terraform, so i can create subscriptions at Project_B to topics of Project_A

google_cloudfunctions_function resource for example, has field called service_account_email for setting service account. But there is no for google_pubsub_subscription resource, for pull subscriptions in the documentation.

Upvotes: 2

Views: 3361

Answers (2)

MBHA Phoenix
MBHA Phoenix

Reputation: 2217

I'm adding another answer, because the question has changes a lot after the different comments.

Here is the solution with the hypothesis that a topic topic-sof is already created in a different project than the subscription one.

  1. I created a service account (SA) on the subscription project, I called it stackoverflow-playground-sa and gave it only the Pub/Sub Editor role as you can see in the screenshot below. enter image description here

  2. I gave the SA the the Pub/Sub Subscriber role on the topic topic-sof s show in the screenshot below. If you don't do this step: you will get this error at terraform apply

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

enter image description here

Of course I did the 2 first steps of roles assignments with a user with enough permissions on both projects

  1. I created a json key file for my SA and downloaded under /path/to/my/key/stackoverflow-playground-sa.json

  2. I authenticated as my SA using

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

So it can be used by terraform to create the subscription.

  1. Here is the terraform configuration to create the subscription
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"
}
  1. Run (apply) my terraform and the subscription pull-subscription-of-topic-in-another-project is created and attached to the topic topic-sof in the other project.

  2. I published a message to topic-sof using the web ui.

  3. Still authenticated as stackoverflow-playground-sa thanks to step 4, I pull the message (using gcloud in my treminal) et voilà message received: enter image description here

To summarise : there is no service account to specify in your terraform configuration for this requirement. The service account and its key is set outside terraform (step 1 to 4) so that terraform process can be authenticated and authorised to create the resources configured (the subscription in our case). Besides using a service account key as in step 4 is a bad practice, security wise. An alternative is to use

gcloud auth application-default login

That will let you set the default credentials of the user of your choice. Given that user has the roles I set for the SA.

Upvotes: 1

MBHA Phoenix
MBHA Phoenix

Reputation: 2217

Actually the service account (service_account_email)is to be specified inside the oidc_token section (you had to go further in the doc :)

below a working example of a push sub with service account and audience (optional)

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"
    }

  }
}

Upvotes: 4

Related Questions