diff --git a/google_project/README.md b/google_project/README.md
index e99323e7..5751a86d 100644
--- a/google_project/README.md
+++ b/google_project/README.md
@@ -9,6 +9,7 @@ Sets up a single GCP project linked to a billing account plus management metadat
| [additional\_data\_access\_logs](#input\_additional\_data\_access\_logs) | Additional services that data access logs should be included for. Google Cloud services with audit logs: https://cloud.google.com/logging/docs/audit/services . | `list(string)` | `[]` | no |
| [app\_code](#input\_app\_code) | Defaults to project\_name. Used for labels and metadata on application-related resources. See https://github.com/mozilla-services/inventory/blob/master/application_component_registry.csv | `string` | `""` | no |
| [billing\_account\_id](#input\_billing\_account\_id) | Associated billing account | `string` | n/a | yes |
+| [cloud\_assist](#input\_cloud\_assist) | Enables the Cloud Assist API set and grants the project's auto-provisioned proactive agent identity the IAM roles it needs. Proactive Mode itself must still be toggled on in the console. | `bool` | `false` | no |
| [component\_code](#input\_component\_code) | Defaults to app\_code-uncat. See https://github.com/mozilla-services/inventory/blob/master/application_component_registry.csv | `string` | `""` | no |
| [cost\_center](#input\_cost\_center) | Cost center of the project or resource. Default is 5650 (Services Engineering) | `string` | `"5650"` | no |
| [deletion\_policy](#input\_deletion\_policy) | The deletion policy for the Project. | `string` | `"PREVENT"` | no |
@@ -16,6 +17,7 @@ Sets up a single GCP project linked to a billing account plus management metadat
| [extra\_project\_labels](#input\_extra\_project\_labels) | Extra project labels (a map of key/value pairs) to be applied to the Project. | `map(string)` | `{}` | no |
| [log\_analytics](#input\_log\_analytics) | Enable log analytics for \_Default log bucket | `bool` | `false` | no |
| [log\_retention\_days](#input\_log\_retention\_days) | Log Retention in days. Defaults to 30 days. | `number` | `30` | no |
+| [organization\_number](#input\_organization\_number) | GCP organization number (the bare numeric id, not the organizations/NUMBER resource name). Used to construct the Cloud Assist proactive agent principal. | `string` | `"442341870013"` | no |
| [parent\_id](#input\_parent\_id) | Parent folder (with GCP). | `string` | n/a | yes |
| [program\_code](#input\_program\_code) | Program Code of the project or resource: https://mana.mozilla.org/wiki/display/FINArchive/Program+Codes. Drop the `PC - `, lowercase the string and substitute spaces for dashes. | `string` | `"firefox-services"` | no |
| [program\_name](#input\_program\_name) | Name of the Firefox program being one of: ci, data, infrastructure, services, web. | `string` | `"services"` | no |
diff --git a/google_project/locals.tf b/google_project/locals.tf
index 21b69f48..5c1210f3 100644
--- a/google_project/locals.tf
+++ b/google_project/locals.tf
@@ -33,7 +33,35 @@ locals {
"stackdriver.googleapis.com",
"privilegedaccessmanager.googleapis.com"
]
- all_project_services = setunion(local.default_project_services, var.project_services)
+ # Gemini Cloud Assist APIs
+ cloud_assist_services = var.cloud_assist ? [
+ "geminicloudassist.googleapis.com", # chat + Investigations
+ "cloudaicompanion.googleapis.com",
+ "designcenter.googleapis.com", # "Required & recommended" APIs
+ "appoptimize.googleapis.com",
+ "apphub.googleapis.com",
+ "apptopology.googleapis.com", # recommended for deeper responses
+ "recommender.googleapis.com",
+ "cloudresourcemanager.googleapis.com", # lets investigations read the project IAM policy
+ "policytroubleshooter.googleapis.com", # lets investigations run IAM Policy Troubleshooter
+ ] : []
+
+ all_project_services = setunion(local.default_project_services, var.project_services, local.cloud_assist_services)
+
+ # Roles the console "Grant access" step assigns to the proactive agent identity
+ cloud_assist_agent_binding_roles = [
+ "roles/iam.supportUser", # proactive troubleshooting
+ "roles/cloudhub.operator", # cost optimization
+ "roles/appoptimize.admin", # cost optimization
+ ]
+ # serviceUsageConsumer is not managed authoritatively as it is occasionally
+ # configured explicitly and non-canonically by tenants
+ cloud_assist_agent_member_roles = [
+ "roles/serviceusage.serviceUsageConsumer", # proactive troubleshooting
+ ]
+
+ # https://docs.cloud.google.com/cloud-assist/proactive-agents-setup#agent_identity_roles
+ cloud_assist_agent_principal = "principal://agents.global.org-${var.organization_number}.system.id.goog/resources/geminicloudassist/projects/${google_project.project.number}/locations/global/agents/cloud"
default_data_access_logs = ["iam.googleapis.com", "secretmanager.googleapis.com", "sts.googleapis.com", "privilegedaccessmanager.googleapis.com"]
data_access_logs_filter = join("\n", toset([for v in concat(local.default_data_access_logs, var.additional_data_access_logs) : "AND NOT protoPayload.serviceName=\"${v}\""]))
diff --git a/google_project/main.tf b/google_project/main.tf
index f2677756..b34b0609 100644
--- a/google_project/main.tf
+++ b/google_project/main.tf
@@ -30,6 +30,35 @@ resource "google_project_service" "project" {
]
}
+# "Grant access" step for Gemini Cloud Assist proactive agents. We may want to
+# move these permissions grants to elsewhere e.g. the permissions module
+# eventually.
+# NOTE: currently Proactive Mode must be toggled on in the console (Gemini
+# Cloud Assist chat > Settings > Proactive Agents) per project
+resource "google_project_iam_binding" "cloud_assist_agent" {
+ for_each = var.cloud_assist ? toset(local.cloud_assist_agent_binding_roles) : toset([])
+
+ project = local.project_id
+ role = each.value
+ members = [local.cloud_assist_agent_principal]
+
+ depends_on = [
+ time_sleep.wait_60_seconds
+ ]
+}
+
+resource "google_project_iam_member" "cloud_assist_agent" {
+ for_each = var.cloud_assist ? toset(local.cloud_assist_agent_member_roles) : toset([])
+
+ project = local.project_id
+ role = each.value
+ member = local.cloud_assist_agent_principal
+
+ depends_on = [
+ time_sleep.wait_60_seconds
+ ]
+}
+
// The project feed requires that cloudasset API is not only set up but also that the service account is created
// Create a service account for the cloudasset API
// ref: https://stackoverflow.com/questions/63785247/gcp-managed-service-account-is-not-created-for-cloud-asset-api
diff --git a/google_project/variables.tf b/google_project/variables.tf
index 513f2666..5a1c1c6b 100644
--- a/google_project/variables.tf
+++ b/google_project/variables.tf
@@ -127,3 +127,15 @@ variable "deletion_policy" {
description = "The deletion policy for the Project."
type = string
}
+
+variable "cloud_assist" {
+ default = false
+ description = "Enables the Cloud Assist API set and grants the project's auto-provisioned proactive agent identity the IAM roles it needs. Proactive Mode itself must still be toggled on in the console."
+ type = bool
+}
+
+variable "organization_number" {
+ default = "442341870013"
+ description = "GCP organization number (the bare numeric id, not the organizations/NUMBER resource name). Used to construct the Cloud Assist proactive agent principal."
+ type = string
+}