From 909b96449def2e8366270239a2151702f3b59a36 Mon Sep 17 00:00:00 2001 From: tmshn Date: Thu, 1 Aug 2019 15:37:30 +0900 Subject: [PATCH 1/2] Add oidcToken field to pubsub subscription --- products/pubsub/api.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/products/pubsub/api.yaml b/products/pubsub/api.yaml index 43b7ebd18971..0e137f8459dd 100644 --- a/products/pubsub/api.yaml +++ b/products/pubsub/api.yaml @@ -141,6 +141,30 @@ objects: - v1beta1: uses the push format defined in the v1beta1 Pub/Sub API. - v1 or v1beta2: uses the push format defined in the v1 Pub/Sub API. + - !ruby/object:Api::Type::NestedObject + name: oidcToken + description: | + If specified, Pub/Sub will generate and attach an OIDC JWT token as + an Authorization header in the HTTP request for every pushed message. + properties: + - !ruby/object:Api::Type::String + name: serviceAccountEmail + required: true + description: | + Service account email to be used for generating the OIDC token. + The caller (for subscriptions.create, UpdateSubscription, and + subscriptions.modifyPushConfig RPCs) must have the + iam.serviceAccounts.actAs permission for the service account. + - !ruby/object:Api::Type::String + name: audience + description: | + Audience to be used when generating OIDC token. The audience + claim identifies the recipients that the JWT is intended for. + The audience value is a single case-sensitive string. Having + multiple values (array) for the audience field is not supported. + More info about the OIDC JWT token audience here: + https://tools.ietf.org/html/rfc7519#section-4.1.3 + Note: if not specified, the Push endpoint URL will be used. - !ruby/object:Api::Type::Integer name: 'ackDeadlineSeconds' description: | From ff275d151a02c2ba0947982b6a83120e41216468 Mon Sep 17 00:00:00 2001 From: tmshn Date: Wed, 14 Aug 2019 16:25:57 +0900 Subject: [PATCH 2/2] Example for pubsub subscription oidcToken (with CloudRun) --- products/pubsub/terraform.yaml | 10 +++ ...scription_push_with_service_account.tf.erb | 67 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 templates/terraform/examples/pubsub_subscription_push_with_service_account.tf.erb diff --git a/products/pubsub/terraform.yaml b/products/pubsub/terraform.yaml index a28ab2073937..eaa5883eeaee 100644 --- a/products/pubsub/terraform.yaml +++ b/products/pubsub/terraform.yaml @@ -63,6 +63,16 @@ overrides: !ruby/object:Overrides::ResourceOverrides topic_project: "topic-project" subscription_name: "example-subscription" subscription_project: "subscription-project" + - !ruby/object:Provider::Terraform::Examples + name: "pubsub_subscription_push_with_service_account" + primary_resource_id: "example" + skip_test: true + vars: + cloudrun_name: "example-cloudrun" + cloudrun_region: "us-central1" + topic_name: "example-topic" + service_account_id: "example-service-account" + subscription_name: "example-subscription" docs: !ruby/object:Provider::Terraform::Docs attributes: | * `path`: Path of the subscription in the format `projects/{project}/subscriptions/{name}` diff --git a/templates/terraform/examples/pubsub_subscription_push_with_service_account.tf.erb b/templates/terraform/examples/pubsub_subscription_push_with_service_account.tf.erb new file mode 100644 index 000000000000..f485a042d79d --- /dev/null +++ b/templates/terraform/examples/pubsub_subscription_push_with_service_account.tf.erb @@ -0,0 +1,67 @@ +data "google_project" "current" {} + +# ------------------ +# CloudRun +# ------------------ +resource "google_cloud_run_service" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['cloudrun_name'] %>" + location = "<%= ctx[:vars]['cloudrun_region'] %>" + provider = "google-beta" + + metadata { + namespace = "${google_project.current.name}" + } + + spec { + containers { + image = "gcr.io/cloudrun/hello" + } + } +} + +# ------------- +# Cloud Pub/Sub +# ------------- +resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['topic_name'] %>" +} + +resource "google_project_iam_member" "pubsub_sa_token_creator" { + role = "roles/iam.serviceAccountTokenCreator" + member = "serviceAccount:service-${google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com" +} + +resource "google_service_account" "<%= ctx[:primary_resource_id] %>" { + account_id = "<%= ctx[:vars]['service_account_id'] %>" +} + +# TODO: grant role only to the CloudRun service rather than project wide. +# (CloudRun service iam policy is not implemented on the Terraform yet) +# ``` +# gcloud beta run services add-iam-policy-binding "${google_cloud_run_service.<%= ctx[:primary_resource_id] %>.name}" \ +# --member="serviceAccount:${google_service_account.<%= ctx[:primary_resource_id] %>.email}" \ +# --role=roles/run.invoker +# ``` +resource "google_project_iam_member" "<%= ctx[:primary_resource_id] %>_run_invoker" { + role = "roles/run.invoker" + member = "serviceAccount:${google_service_account.<%= ctx[:primary_resource_id] %>.email}" +} + +resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['subscription_name'] %>" + topic = "${google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name}" + + push_config { + # TODO: this must be CloudRun's url, which is not currently exposed on the Terraform + # push_endpoint = "${google_cloud_run_service.<%= ctx[:primary_resource_id] %>.status.url}" + push_endpoint = "https://example.com/push" + + attributes { + x-goog-version = "v1" + } + + oidcToken { + serviceAccountEmail = "${google_service_account.<%= ctx[:primary_resource_id] %>.email}" + } + } +}