terraform-google-modules / terraform-example-foundation

Shows how the CFT modules can be composed to build a secure cloud foundation
https://cloud.google.com/architecture/security-foundations
Apache License 2.0
1.18k stars 701 forks source link

Recurring permissions issue when deploying the cloud function for SCC notification, resulting in tfstate corruption #1269

Open mromascanu123 opened 2 weeks ago

mromascanu123 commented 2 weeks ago

TL;DR

When deploying 1-org deployment of a cloud function fails:

2024-06-17T16:10:56.4401141Z module.logs_export.module.destination_aggregated_logs[0].google_logging_linked_dataset.linked_dataset[0]: Creation complete after 1m26s [id=projects/prj-c-logging-p2b3/locations/northamerica-northeast1/buckets/AggregatedLogs/links/ds_c_prj_aggregated_logs_analytics] 2024-06-17T16:10:56.6506201Z time_sleep.wait_logs_export: Creating... 2024-06-17T16:11:06.6507192Z time_sleep.wait_logs_export: Still creating... [10s elapsed] 2024-06-17T16:11:16.6511807Z time_sleep.wait_logs_export: Still creating... [20s elapsed] 2024-06-17T16:11:26.6522464Z time_sleep.wait_logs_export: Still creating... [30s elapsed] 2024-06-17T16:11:26.6746343Z time_sleep.wait_logs_export: Creation complete after 30s [id=2024-06-17T16:11:26Z] 2024-06-17T16:11:26.9026161Z module.org_domain_restricted_sharing.data.google_organization.orgs["gcp.mcn.gouv.qc.ca"]: Reading... 2024-06-17T16:11:27.1759510Z module.org_domain_restricted_sharing.data.google_organization.orgs["gcp.mcn.gouv.qc.ca"]: Read complete after 0s [id=organizations/946862951350] 2024-06-17T16:11:27.1812859Z module.org_domain_restricted_sharing.module.allowed-policy-member-domains.google_folder_organization_policy.folder_policy_list_allow_values[0]: Creating... 2024-06-17T16:11:27.9433964Z module.org_domain_restricted_sharing.module.allowed-policy-member-domains.google_folder_organization_policy.folder_policy_list_allow_values[0]: Creation complete after 1s [id=734742217357/constraints/iam.allowedPolicyMemberDomains] 2024-06-17T16:11:28.1309446Z ### 2024-06-17T16:11:28.1311289Z Error: Error waiting to create function: Error waiting for Creating function: Error code 13, message: Build failed with status: FAILURE and message: failed to Fetch: failed to download archive gs://gcf-v2-sources-231250091961-northamerica-northeast1/caiMonitoring/function-source.zip: Access to bucket gcf-v2-sources-231250091961-northamerica-northeast1 denied. You must grant Storage Object Viewer permission to 231250091961-compute@developer.gserviceaccount.com. 2024-06-17T16:11:28.1312489Z . For more details see the logs at https://console.cloud.google.com/cloud-build/builds;region=northamerica-northeast1/206fa3d2-6c5c-49a7-a213-bed936b9a10d?project=231250091961. 2024-06-17T16:11:28.1312959Z 2024-06-17T16:11:28.1313522Z with module.cai_monitoring.module.cloud_function.google_cloudfunctions2_function.function, 2024-06-17T16:11:28.1313841Z on .terraform/modules/cai_monitoring.cloud_function/main.tf line 21, in resource "google_cloudfunctions2_function" "function": 2024-06-17T16:11:28.1314196Z 21: resource "google_cloudfunctions2_function" "function" {

Subsequent stages report missing outputs from 1-org tfstate

2024-06-17T09:36:44.3089085Z envs/production doesn't match nonproduction; skipping 2024-06-17T09:36:44.3136431Z * TERRAFORM PLAN ***** 2024-06-17T09:36:44.3136909Z At environment: envs/nonproduction 2024-06-17T09:36:44.3137320Z ** 2024-06-17T09:36:47.7495471Z module.base_env.data.terraform_remote_state.bootstrap: Reading... ...

2024-06-17T09:36:48.9745292Z + restricted_subnets_names = [ 2024-06-17T09:36:48.9745510Z + "sb-n-shared-restricted-northamerica-northeast1", 2024-06-17T09:36:48.9745772Z + "sb-n-shared-restricted-northamerica-northeast1-proxy", 2024-06-17T09:36:48.9745905Z ] 2024-06-17T09:36:48.9745943Z 2024-06-17T09:36:48.9746068Z Error: Unsupported attribute 2024-06-17T09:36:48.9746129Z 2024-06-17T09:36:48.9746259Z on ../../modules/base_env/remote.tf line 18, in locals: 2024-06-17T09:36:48.9746509Z 18: restricted_project_id = data.terraform_remote_state.org.outputs.shared_vpc_projects[var.env].restricted_shared_vpc_project_id 2024-06-17T09:36:48.9746782Z ├──────────────── 2024-06-17T09:36:48.9747034Z │ data.terraform_remote_state.org.outputs is object with 27 attributes 2024-06-17T09:36:48.9747143Z 2024-06-17T09:36:48.9747282Z This object does not have an attribute named "shared_vpc_projects". 2024-06-17T09:36:48.9751658Z 2024-06-17T09:36:48.9752037Z Error: Unsupported attribute 2024-06-17T09:36:48.9752218Z 2024-06-17T09:36:48.9752628Z on ../../modules/base_env/remote.tf line 19, in locals: 2024-06-17T09:36:48.9753359Z 19: restricted_project_number = data.terraform_remote_state.org.outputs.shared_vpc_projects[var.env].restricted_shared_vpc_project_number 2024-06-17T09:36:48.9754185Z ├──────────────── 2024-06-17T09:36:48.9754425Z │ data.terraform_remote_state.org.outputs is object with 27 attributes 2024-06-17T09:36:48.9754518Z 2024-06-17T09:36:48.9754672Z This object does not have an attribute named "shared_vpc_projects". 2024-06-17T09:36:48.9754759Z 2024-06-17T09:36:48.9754869Z Error: Unsupported attribute 2024-06-17T09:36:48.9754945Z 2024-06-17T09:36:48.9755074Z on ../../modules/base_env/remote.tf line 20, in locals: 2024-06-17T09:36:48.9755311Z 20: base_project_id = data.terraform_remote_state.org.outputs.shared_vpc_projects[var.env].base_shared_vpc_project_id 2024-06-17T09:36:48.9755571Z ├──────────────── 2024-06-17T09:36:48.9755801Z │ data.terraform_remote_state.org.outputs is object with 27 attributes 2024-06-17T09:36:48.9755914Z 2024-06-17T09:36:48.9756054Z This object does not have an attribute named "shared_vpc_projects".

Expected behavior

The compute SA used by cloudbuild to deploy the function is created deep down in the TF libraries as a result of invoking "GoogleCloudPlatform/cloud-functions/google" in 1-org/modules/cai-monitoring/main.tf and there is nothing in the parameters suggesting any IAM permissions being provided for accessing the code in the bucket

// Cloud Function module "cloud_function" { source = "GoogleCloudPlatform/cloud-functions/google" version = "0.4.1"

function_name = "caiMonitoring" description = "Check on the Organization for members (users, groups and service accounts) that contains the IAM roles listed." project_id = var.project_id labels = var.labels function_location = var.location runtime = "nodejs20" entrypoint = "caiMonitoring" docker_repository = google_artifact_registry_repository.cloudfunction.id

storage_source = { bucket = module.cloudfunction_source_bucket.name object = google_storage_bucket_object.cf_cai_source_zip.name }

The bucket object holding the source code created as well in the same section resource "google_storage_bucket_object" "cf_cai_source_zip" { name = "${path.module}/cai_monitoring.zip" bucket = module.cloudfunction_source_bucket.name source = data.archive_file.function_source_zip.output_path

depends_on = [ time_sleep.wait_for_bucket ] }

Observed behavior

Unexpected permission-related issue - deployment of cloud function invokes cloudbuild behind the scenes and fails

Terraform Configuration

N/A

Terraform Version

1.6.0

Additional information

No response

eeaton commented 2 weeks ago

I'm not able to recreate this in our test environment but it looks like you've been impacted by the platform-wide security update regarding the cloud build service account change [1]. Your log indicates the identity without the necessary permissions to read from the the AR bucket is the Compute default service account, (231250091961-compute@developer.gserviceaccount.com), not the legacy default Build service account (231250091961@cloudbuild.gserviceaccount.com), which is consistent with the change. Because we're also enforcing the org policy to prevent default Editor roles on the Compute service account, it has no permissions so Cloud Build will fail.

As far as I can tell, the provider module for Cloud Functions [2] does not have the ability to specify which service account is used for the underlying build. I'll raise an issue but suspect we can't fix it cleanly in terraform until that is improved.

As a short term workaround, you can try explicitly setting the Compute default service account in the project prj-c-scc to have the permissions documented on [2], or setting the Org policies documented in [1] .

[1] https://cloud.google.com/build/docs/cloud-build-service-account-updates [2] https://registry.terraform.io/modules/GoogleCloudPlatform/cloud-functions/google/latest

caetano-colin commented 1 week ago

I faced the same issue when deploying the codebase and managed to fix it by assigning roles/logging.logWriter, roles/storage.objectViewer and roles/artifactregistry.writer to the default Compute Engine SA on SCC project.

eeaton commented 1 week ago

Thanks for confirming the permissions and raising the upstream PR, @caetano-colin.

I'll chase the maintainers of terraform-google-cloud-functions to get that approved, then make a PR to specify a custom build service account in this repo. ( since we are recommending against the use of the default compute service account, I think it's a cleaner fix to specify a user managed service account with those necessary roles instead of relying on the default compute service account.)