diff --git a/blueprints/data-solutions/bq-ml/README.md b/blueprints/data-solutions/bq-ml/README.md index eabfe9d69b..39a9c0decc 100644 --- a/blueprints/data-solutions/bq-ml/README.md +++ b/blueprints/data-solutions/bq-ml/README.md @@ -97,5 +97,5 @@ module "test" { prefix = "prefix" } -# tftest modules=9 resources=68 +# tftest modules=9 resources=69 ``` diff --git a/blueprints/data-solutions/data-playground/README.md b/blueprints/data-solutions/data-playground/README.md index 34824bf695..9890619d38 100644 --- a/blueprints/data-solutions/data-playground/README.md +++ b/blueprints/data-solutions/data-playground/README.md @@ -84,5 +84,5 @@ module "test" { parent = "folders/467898377" } } -# tftest modules=8 resources=67 +# tftest modules=8 resources=68 ``` diff --git a/blueprints/data-solutions/vertex-mlops/README.md b/blueprints/data-solutions/vertex-mlops/README.md index 6277c4f528..6c4e5913de 100644 --- a/blueprints/data-solutions/vertex-mlops/README.md +++ b/blueprints/data-solutions/vertex-mlops/README.md @@ -72,7 +72,7 @@ module "test" { project_id = "test-dev" } } -# tftest modules=11 resources=89 +# tftest modules=11 resources=90 ``` ## Variables @@ -128,5 +128,5 @@ module "test" { project_id = "test-dev" } } -# tftest modules=13 resources=94 e2e +# tftest modules=13 resources=95 e2e ``` diff --git a/modules/project/service-agents.yaml b/modules/project/service-agents.yaml index 8590aafb93..e7815218cf 100644 --- a/modules/project/service-agents.yaml +++ b/modules/project/service-agents.yaml @@ -787,6 +787,13 @@ role: null is_primary: false aliases: [] +- name: gcp-ri-contactcenterinsights + display_name: Contact Center Insights Resource Identity (prod) + api: contactcenterinsights.googleapis.com + identity: service-%s@gcp-ri-contactcenterinsights.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] - name: container-analysis display_name: Container Analysis Service Agent api: containeranalysis.googleapis.com @@ -969,6 +976,13 @@ role: roles/firebaseapphosting.serviceAgent is_primary: true aliases: [] +- name: crashlytics + display_name: Firebase Crashlytics Service Agent + api: firebasecrashlytics.googleapis.com + identity: service-%s@gcp-sa-crashlytics.iam.gserviceaccount.com + role: roles/firebasecrashlytics.serviceAgent + is_primary: true + aliases: [] - name: firebasedataconnect display_name: Firebase Data Connect Service Account api: firebasedataconnect.googleapis.com @@ -1173,13 +1187,6 @@ role: null is_primary: false aliases: [] -- name: chronicle-spanner - display_name: Internal Chronicle Spanner Service Account - api: chronicle.googleapis.com - identity: service-%s@gcp-sa-chronicle-spanner.iam.gserviceaccount.com - role: null - is_primary: false - aliases: [] - name: fs-spanner display_name: Internal Cloud Firestore Spanner Service Agent api: firestore.googleapis.com @@ -1351,6 +1358,13 @@ role: null is_primary: true aliases: [] +- name: progrollout + display_name: Progressive Rollout Service Agent + api: progressiverollout.googleapis.com + identity: service-%s@gcp-sa-progrollout.iam.gserviceaccount.com + role: roles/progressiverollout.serviceAgent + is_primary: true + aliases: [] - name: pubsublite display_name: Pub/Sub Lite Service Account api: pubsublite.googleapis.com @@ -1572,7 +1586,7 @@ display_name: Vertex AI Online Prediction Service Agent api: aiplatform.googleapis.com identity: service-%s@gcp-sa-vertex-op.iam.gserviceaccount.com - role: null + role: roles/aiplatform.onlinePredictionServiceAgent is_primary: false aliases: [] - name: vertex-tune diff --git a/tests/examples_e2e/setup_module/jit.tf.json b/tests/examples_e2e/setup_module/jit.tf.json new file mode 100644 index 0000000000..d2a9c8cedd --- /dev/null +++ b/tests/examples_e2e/setup_module/jit.tf.json @@ -0,0 +1,28 @@ +{ + "locals": { + "jit_services": { + "alloydb.googleapis.com": "roles/alloydb.serviceAgent", + "apigee.googleapis.com": "roles/apigee.serviceAgent", + "artifactregistry.googleapis.com": "roles/artifactregistry.serviceAgent", + "assuredworkloads.googleapis.com": "roles/assuredworkloads.serviceAgent", + "dns.googleapis.com": "roles/dns.serviceAgent", + "dataplex.googleapis.com": "roles/dataplex.serviceAgent", + "pubsub.googleapis.com": "roles/pubsub.serviceAgent", + "sqladmin.googleapis.com": "roles/cloudsql.serviceAgent", + "dataform.googleapis.com": "roles/dataform.serviceAgent", + "eventarc.googleapis.com": "roles/eventarc.serviceAgent", + "cloudkms.googleapis.com": null, + "dataproc.googleapis.com": "roles/dataproc.serviceAgent", + "cloudfunctions.googleapis.com": "roles/cloudfunctions.serviceAgent", + "run.googleapis.com": "roles/run.serviceAgent", + "iap.googleapis.com": null, + "container.googleapis.com": "roles/container.serviceAgent", + "looker.googleapis.com": "roles/looker.serviceAgent", + "monitoring.googleapis.com": "roles/monitoring.notificationServiceAgent", + "networkconnectivity.googleapis.com": "roles/networkconnectivity.serviceAgent", + "secretmanager.googleapis.com": null, + "vpcaccess.googleapis.com": "roles/vpcaccess.serviceAgent", + "servicenetworking.googleapis.com": "roles/servicenetworking.serviceAgent" + } + } +} diff --git a/tests/examples_e2e/setup_module/main.tf b/tests/examples_e2e/setup_module/main.tf index 82b59b8402..47db8dfb34 100644 --- a/tests/examples_e2e/setup_module/main.tf +++ b/tests/examples_e2e/setup_module/main.tf @@ -14,15 +14,13 @@ locals { prefix = "${var.prefix}-${var.timestamp}${var.suffix}" - jit_services = [ - "alloydb.googleapis.com", # no permissions granted by default - "artifactregistry.googleapis.com", # roles/artifactregistry.serviceAgent - "pubsub.googleapis.com", # roles/pubsub.serviceAgent - "storage.googleapis.com", # no permissions granted by default - "sqladmin.googleapis.com", # roles/cloudsql.serviceAgent - ] services = [ - # trimmed down list of services, to be extended as needed + # trimmed down list of services, to be extended as needed. If you + # update this list, make sure to update E2E_SERVICES in + # tools/built_service_agents.py and run: + # + # python tools/build_service_agents.py --e2e > tests/examples_e2e/setup_module/jit.tf.json + # "alloydb.googleapis.com", "analyticshub.googleapis.com", "apigee.googleapis.com", @@ -212,6 +210,7 @@ resource "google_service_networking_connection" "psa_connection" { service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.psa_ranges.name] deletion_policy = "ABANDON" + depends_on = [google_project_iam_binding.agents] } ### END OF PSA @@ -223,33 +222,24 @@ resource "google_service_account" "service_account" { } resource "google_project_service_identity" "jit_si" { - for_each = toset(local.jit_services) + for_each = local.jit_services provider = google-beta project = google_project.project.project_id - service = each.value + service = each.key depends_on = [google_project_service.project_service] } -resource "google_project_iam_binding" "cloudsql_agent" { - members = ["serviceAccount:service-${google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com"] - project = google_project.project.project_id - role = "roles/cloudsql.serviceAgent" - depends_on = [google_project_service_identity.jit_si] -} - -resource "google_project_iam_binding" "artifactregistry_agent" { - members = ["serviceAccount:service-${google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com"] - project = google_project.project.project_id - role = "roles/artifactregistry.serviceAgent" - depends_on = [google_project_service_identity.jit_si] +resource "google_project_iam_binding" "agents" { + for_each = { + for k, v in local.jit_services : k => v if v != null + } + members = [ + google_project_service_identity.jit_si[each.key].member + ] + project = google_project.project.project_id + role = each.value } -resource "google_project_iam_binding" "pubsub_agent" { - members = ["serviceAccount:service-${google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com"] - project = google_project.project.project_id - role = "roles/pubsub.serviceAgent" - depends_on = [google_project_service_identity.jit_si] -} resource "local_file" "terraform_tfvars" { filename = "e2e_tests.tfvars" diff --git a/tools/build_service_agents.py b/tools/build_service_agents.py index c8dc0690da..65e22d28b2 100755 --- a/tools/build_service_agents.py +++ b/tools/build_service_agents.py @@ -17,6 +17,8 @@ from dataclasses import asdict, dataclass from itertools import chain +import click +import json import requests import yaml from bs4 import BeautifulSoup @@ -41,6 +43,42 @@ 'serverless-robot-prod': ['cloudrun', 'run'], } +E2E_SERVICES = [ + "alloydb.googleapis.com", + "analyticshub.googleapis.com", + "apigee.googleapis.com", + "artifactregistry.googleapis.com", + "assuredworkloads.googleapis.com", + "bigquery.googleapis.com", + "cloudbuild.googleapis.com", + "cloudfunctions.googleapis.com", + "cloudkms.googleapis.com", + "cloudresourcemanager.googleapis.com", + "compute.googleapis.com", + "container.googleapis.com", + "dataform.googleapis.com", + "dataplex.googleapis.com", + "dataproc.googleapis.com", + "dns.googleapis.com", + "eventarc.googleapis.com", + "iam.googleapis.com", + "iap.googleapis.com", + "logging.googleapis.com", + "looker.googleapis.com", + "monitoring.googleapis.com", + "networkconnectivity.googleapis.com", + "pubsub.googleapis.com", + "run.googleapis.com", + "secretmanager.googleapis.com", + "servicenetworking.googleapis.com", + "serviceusage.googleapis.com", + "sqladmin.googleapis.com", + "stackdriver.googleapis.com", + "storage-component.googleapis.com", + "storage.googleapis.com", + "vpcaccess.googleapis.com", +] + PRIMARY_OVERRIDE = { 'storage-transfer-service': True, } @@ -57,7 +95,9 @@ class Agent: aliases: list[str] -def main(): +@click.command() +@click.option('--e2e', is_flag=True, default=False) +def main(e2e=False): page = requests.get(SERVICE_AGENTS_URL).content soup = BeautifulSoup(page, 'html.parser') agents = [] @@ -115,11 +155,19 @@ def main(): aliases = set(chain.from_iterable(agent.aliases for agent in agents)) assert aliases.isdisjoint(names) - # take the header from the first lines of this file - header = open(__file__).readlines()[2:15] - print("".join(header)) - # and print all the agents - print(yaml.safe_dump([asdict(a) for a in agents], sort_keys=False)) + if not e2e: + # take the header from the first lines of this file + header = open(__file__).readlines()[2:15] + print("".join(header)) + # and print all the agents + print(yaml.safe_dump([asdict(a) for a in agents], sort_keys=False)) + else: + jit_services = {} + result = {"locals": {"jit_services": jit_services}} + for a in agents: + if a.is_primary and a.api in E2E_SERVICES: + jit_services[a.api] = a.role + print(json.dumps(result, indent=2)) if __name__ == '__main__':