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