diff --git a/modules/cloud-run/README.md b/modules/cloud-run/README.md
index cfd4d7928..cd655a5f6 100644
--- a/modules/cloud-run/README.md
+++ b/modules/cloud-run/README.md
@@ -218,6 +218,57 @@ module "cloud_run" {
# tftest modules=1 resources=2 inventory=audit-logs.yaml
```
+#### Using custom service accounts for triggers
+
+By default `Compute default service account` is used to trigger Cloud Run. If you want to use custom Service Account you can either provide your own in `eventarc_triggers.service_account_email` or set `eventarc_triggers.service_account_create` to true and service account named `tf-cr-trigger-${var.name}` will be created with `roles/run.invoker` granted on this Cloud Run service.
+
+Example using provided service account:
+```hcl
+module "cloud_run" {
+ source = "./fabric/modules/cloud-run"
+ project_id = "my-project"
+ name = "hello"
+ containers = {
+ hello = {
+ image = "us-docker.pkg.dev/cloudrun/container/hello"
+ }
+ }
+ eventarc_triggers = {
+ audit_log = {
+ setiampolicy = {
+ method = "SetIamPolicy"
+ service = "cloudresourcemanager.googleapis.com"
+ }
+ }
+ service_account_email = "cloud-run-trigger@my-project.iam.gserviceaccount.com"
+ }
+}
+# tftest modules=1 resources=2 inventory=trigger-service-account-external.yaml
+```
+
+Example using automatically created service account:
+```hcl
+module "cloud_run" {
+ source = "./fabric/modules/cloud-run"
+ project_id = "my-project"
+ name = "hello"
+ containers = {
+ hello = {
+ image = "us-docker.pkg.dev/cloudrun/container/hello"
+ }
+ }
+ eventarc_triggers = {
+ pubsub = {
+ topic-1 = "topic1"
+ topic-2 = "topic2"
+ }
+ service_account_create = true
+ }
+}
+# tftest modules=1 resources=5 inventory=trigger-service-account.yaml
+```
+
+
### Service account
To use a custom service account managed by the module, set `service_account_create` to `true` and leave `service_account` set to `null` value (default).
@@ -259,24 +310,24 @@ module "cloud_run" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L121) | Name used for cloud run service. | string | ✓ | |
-| [project_id](variables.tf#L136) | Project id used for all resources. | string | ✓ | |
+| [name](variables.tf#L123) | Name used for cloud run service. | string | ✓ | |
+| [project_id](variables.tf#L138) | Project id used for all resources. | string | ✓ | |
| [container_concurrency](variables.tf#L18) | Maximum allowed in-flight (concurrent) requests per container of the revision. | string | | null |
| [containers](variables.tf#L24) | Containers in arbitrary key => attributes format. | map(object({…})) | | {} |
-| [eventarc_triggers](variables.tf#L91) | Event arc triggers for different sources. | object({…}) | | {} |
-| [iam](variables.tf#L103) | IAM bindings for Cloud Run service in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
-| [ingress_settings](variables.tf#L109) | Ingress settings. | string | | null |
-| [labels](variables.tf#L115) | Resource labels. | map(string) | | {} |
-| [prefix](variables.tf#L126) | Optional prefix used for resource names. | string | | null |
-| [region](variables.tf#L141) | Region used for all resources. | string | | "europe-west1" |
-| [revision_annotations](variables.tf#L147) | Configure revision template annotations. | object({…}) | | {} |
-| [revision_name](variables.tf#L162) | Revision name. | string | | null |
-| [service_account](variables.tf#L168) | Service account email. Unused if service account is auto-created. | string | | null |
-| [service_account_create](variables.tf#L174) | Auto-create service account. | bool | | false |
-| [timeout_seconds](variables.tf#L180) | Maximum duration the instance is allowed for responding to a request. | number | | null |
-| [traffic](variables.tf#L186) | Traffic steering configuration. If revision name is null the latest revision will be used. | map(object({…})) | | {} |
-| [volumes](variables.tf#L197) | Named volumes in containers in name => attributes format. | map(object({…})) | | {} |
-| [vpc_connector_create](variables.tf#L211) | Populate this to create a VPC connector. You can then refer to it in the template annotations. | object({…}) | | null |
+| [eventarc_triggers](variables.tf#L91) | Event arc triggers for different sources. | object({…}) | | {} |
+| [iam](variables.tf#L105) | IAM bindings for Cloud Run service in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
+| [ingress_settings](variables.tf#L111) | Ingress settings. | string | | null |
+| [labels](variables.tf#L117) | Resource labels. | map(string) | | {} |
+| [prefix](variables.tf#L128) | Optional prefix used for resource names. | string | | null |
+| [region](variables.tf#L143) | Region used for all resources. | string | | "europe-west1" |
+| [revision_annotations](variables.tf#L149) | Configure revision template annotations. | object({…}) | | {} |
+| [revision_name](variables.tf#L164) | Revision name. | string | | null |
+| [service_account](variables.tf#L170) | Service account email. Unused if service account is auto-created. | string | | null |
+| [service_account_create](variables.tf#L176) | Auto-create service account. | bool | | false |
+| [timeout_seconds](variables.tf#L182) | Maximum duration the instance is allowed for responding to a request. | number | | null |
+| [traffic](variables.tf#L188) | Traffic steering configuration. If revision name is null the latest revision will be used. | map(object({…})) | | {} |
+| [volumes](variables.tf#L199) | Named volumes in containers in name => attributes format. | map(object({…})) | | {} |
+| [vpc_connector_create](variables.tf#L213) | Populate this to create a VPC connector. You can then refer to it in the template annotations. | object({…}) | | null |
## Outputs
diff --git a/modules/cloud-run/main.tf b/modules/cloud-run/main.tf
index f2d8e327f..f982081be 100644
--- a/modules/cloud-run/main.tf
+++ b/modules/cloud-run/main.tf
@@ -35,6 +35,17 @@ locals {
"run.googleapis.com/ingress" = var.ingress_settings
}
)
+ _iam_run_invoker_members = concat(
+ lookup(var.iam, "roles/run.invoker", []),
+ var.eventarc_triggers.service_account_create ? ["serviceAccount:${local.trigger_service_account_email}"] : []
+ )
+ iam = merge(
+ var.iam,
+ length(local._iam_run_invoker_members) == 0 ? {} :
+ {
+ "roles/run.invoker" : local._iam_run_invoker_members
+ },
+ )
prefix = var.prefix == null ? "" : "${var.prefix}-"
revision_annotations = merge(
try(var.revision_annotations.autoscaling, null) == null ? {} : {
@@ -73,6 +84,17 @@ locals {
)
: var.service_account
)
+ trigger_service_account_email = (
+ var.eventarc_triggers.service_account_create
+ ? (
+ length(google_service_account.trigger_service_account) > 0
+ ? google_service_account.trigger_service_account[0].email
+ # : google_service_account.trigger_service_account[0].email # : null
+ : null
+ )
+ : var.eventarc_triggers.service_account_email
+ )
+
vpc_connector_create = var.vpc_connector_create != null
}
@@ -288,7 +310,7 @@ resource "google_cloud_run_service" "service" {
}
resource "google_cloud_run_service_iam_binding" "binding" {
- for_each = var.iam
+ for_each = local.iam
project = google_cloud_run_service.service.project
location = google_cloud_run_service.service.location
service = google_cloud_run_service.service.name
@@ -326,6 +348,7 @@ resource "google_eventarc_trigger" "audit_log_triggers" {
region = google_cloud_run_service.service.location
}
}
+ service_account = local.trigger_service_account_email
}
resource "google_eventarc_trigger" "pubsub_triggers" {
@@ -348,4 +371,12 @@ resource "google_eventarc_trigger" "pubsub_triggers" {
region = google_cloud_run_service.service.location
}
}
+ service_account = local.trigger_service_account_email
+}
+
+resource "google_service_account" "trigger_service_account" {
+ count = var.eventarc_triggers.service_account_create ? 1 : 0 # coalesce(try(var.eventarc_triggers.service_account_create, false), false) ? 1 : 0
+ project = var.project_id
+ account_id = "tf-cr-trigger-${var.name}"
+ display_name = "Terraform trigger for Cloud Run ${var.name}."
}
diff --git a/modules/cloud-run/variables.tf b/modules/cloud-run/variables.tf
index afeeb4dde..69499c182 100644
--- a/modules/cloud-run/variables.tf
+++ b/modules/cloud-run/variables.tf
@@ -95,7 +95,9 @@ variable "eventarc_triggers" {
method = string
service = string
})), {})
- pubsub = optional(map(string), {})
+ pubsub = optional(map(string), {})
+ service_account_email = optional(string)
+ service_account_create = optional(bool, false)
})
default = {}
}
diff --git a/tests/modules/cloud_run/examples/trigger-service-account-external.yaml b/tests/modules/cloud_run/examples/trigger-service-account-external.yaml
new file mode 100644
index 000000000..def9c89a2
--- /dev/null
+++ b/tests/modules/cloud_run/examples/trigger-service-account-external.yaml
@@ -0,0 +1,22 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.cloud_run.google_cloud_run_service.service: {}
+ module.cloud_run.google_eventarc_trigger.audit_log_triggers["setiampolicy"]:
+ service_account: cloud-run-trigger@my-project.iam.gserviceaccount.com
+
+counts:
+ google_cloud_run_service: 1
+ google_eventarc_trigger: 1
diff --git a/tests/modules/cloud_run/examples/trigger-service-account.yaml b/tests/modules/cloud_run/examples/trigger-service-account.yaml
new file mode 100644
index 000000000..86b1e1afa
--- /dev/null
+++ b/tests/modules/cloud_run/examples/trigger-service-account.yaml
@@ -0,0 +1,35 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.cloud_run.google_cloud_run_service.service: {}
+ module.cloud_run.google_cloud_run_service_iam_binding.binding["roles/run.invoker"]:
+ project: my-project
+ role: roles/run.invoker
+ service: hello
+ # members: ["known after apply"]
+ module.cloud_run.google_eventarc_trigger.pubsub_triggers["topic-1"]: {}
+ # service_account: known after apply
+ module.cloud_run.google_eventarc_trigger.pubsub_triggers["topic-2"]: {}
+ # service_account: known after apply
+ module.cloud_run.google_service_account.trigger_service_account[0]:
+ account_id: tf-cr-trigger-hello
+ display_name: Terraform trigger for Cloud Run hello.
+ project: my-project
+
+counts:
+ google_cloud_run_service: 1
+ google_cloud_run_service_iam_binding: 1
+ google_eventarc_trigger: 2
+ google_service_account: 1