diff --git a/post-scan-actions/gcp-python-promote-or-quarantine/.gitignore b/post-scan-actions/gcp-python-promote-or-quarantine/.gitignore new file mode 100644 index 0000000..bf0c34e --- /dev/null +++ b/post-scan-actions/gcp-python-promote-or-quarantine/.gitignore @@ -0,0 +1 @@ +main.auto.tfvars diff --git a/post-scan-actions/gcp-python-promote-or-quarantine/main.auto.tfvars.example b/post-scan-actions/gcp-python-promote-or-quarantine/main.auto.tfvars.example index 3739c56..94df9c7 100644 --- a/post-scan-actions/gcp-python-promote-or-quarantine/main.auto.tfvars.example +++ b/post-scan-actions/gcp-python-promote-or-quarantine/main.auto.tfvars.example @@ -6,7 +6,19 @@ deployment_name = "" // e.g. test-deployment scan_result_topic = "" // e.g. my-deployment-scan-result-topic scanning_bucket = "" // e.g. scanning-gcs-bucket -quarantine_mode = "move" // move or copy leave it empty + +// quarantine settings +quarantine_mode = "move" // move or copy. default is move. quarantine_bucket = "" // e.g. quarantine-gcs-bucket Leave it empty if you don't want to quarantine files. -promote_mode = "move" // move or copy +quarantine_bucket_properties = { // additional properties for the quarantine bucket used when cross project or cross region is needed. + region = "" // e.g. us-central1 + project_id = "" // e.g. test-project-998877 +} + +// promote settings +promote_mode = "move" // move or copy. default is move. promote_bucket = "" // e.g. promote-gcs-bucket Leave it empty if you don't want to promote files. +promote_bucket_properties = { // additional properties for the promote bucket used when cross project or cross region is needed. + region = "" // e.g. us-central1 + project_id = "" // e.g. test-project-998877 +} diff --git a/post-scan-actions/gcp-python-promote-or-quarantine/main.tf b/post-scan-actions/gcp-python-promote-or-quarantine/main.tf index ab89c0a..122722f 100644 --- a/post-scan-actions/gcp-python-promote-or-quarantine/main.tf +++ b/post-scan-actions/gcp-python-promote-or-quarantine/main.tf @@ -1,15 +1,6 @@ -terraform { - required_providers { - google = { - source = "hashicorp/google" - version = "~> 5.11.0" - } - } -} - -provider "google" { - project = var.project_id - region = var.region +locals { + promote_enabled = var.promote_bucket != "" + quarantine_enabled = var.quarantine_bucket != "" } resource "random_id" "deploy_suffix" { @@ -28,61 +19,69 @@ data "archive_file" "source" { } resource "google_service_account" "service_account" { - account_id = "qua-pro-plugin-sa-${lower(random_id.deploy_suffix.hex)}" - display_name = "Quarantine/Promote plugin Service Account ${random_id.deploy_suffix.hex}" - project = var.project_id + account_id = "qua-pro-plugin-sa-${lower(random_id.deploy_suffix.hex)}" + display_name = "TM FSS Quarantine/Promote plugin Service Account ${random_id.deploy_suffix.hex}" + project = var.project_id } -resource "google_project_iam_custom_role" "promote_and_quarantine_bucket_role" { - role_id = "plugin_storage_bucket_write_${lower(random_id.deploy_suffix.hex)}" - title = "Promote/Quarantine Bucket Write ${random_id.deploy_suffix.hex}" +resource "google_project_iam_custom_role" "promote_bucket_role" { + count = local.promote_enabled ? 1 : 0 + role_id = "promote_bucket_write_${lower(random_id.deploy_suffix.hex)}" + title = "Promote Bucket Write ${random_id.deploy_suffix.hex}" permissions = [ "storage.objects.create", "storage.objects.delete", "storage.objects.update" ] + provider = google.promote_provider +} + +resource "google_project_iam_custom_role" "quarantine_bucket_role" { + count = local.quarantine_enabled ? 1 : 0 + role_id = "quarantine_bucket_write_${lower(random_id.deploy_suffix.hex)}" + title = "Quarantine Bucket Write ${random_id.deploy_suffix.hex}" + permissions = [ + "storage.objects.create", + "storage.objects.delete", + "storage.objects.update" + ] + provider = google.quarantine_provider } resource "google_project_iam_custom_role" "scanning_bucket_access_role" { role_id = "plugin_storage_bucket_access_${lower(random_id.deploy_suffix.hex)}" - title = "Scanning Bucket Access ${random_id.deploy_suffix.hex}" + title = "Scanning Bucket Access ${random_id.deploy_suffix.hex}" permissions = var.promote_mode == "move" || var.quarantine_mode == "move" ? [ "storage.objects.delete", "storage.objects.get", "storage.objects.update" - ] : [ + ] : [ "storage.objects.get", "storage.objects.update" ] + project = var.project_id + provider = google } -resource "google_storage_bucket_iam_binding" "binding_promote_bucket" { - count = var.promote_bucket != "" ? 1 : 0 - bucket = var.promote_bucket - role = google_project_iam_custom_role.promote_and_quarantine_bucket_role.name - members = [ - "serviceAccount:${google_service_account.service_account.email}", - ] - depends_on = [ - google_project_iam_custom_role.promote_and_quarantine_bucket_role - ] +resource "google_storage_bucket_iam_member" "binding_promote_bucket" { + count = local.promote_enabled != "" ? 1 : 0 + bucket = var.promote_bucket + role = google_project_iam_custom_role.promote_bucket_role[0].id + member = "serviceAccount:${google_service_account.service_account.email}" + provider = google.promote_provider } -resource "google_storage_bucket_iam_binding" "binding_quarantine_bucket" { - count = var.quarantine_bucket != "" ? 1 : 0 - bucket = var.quarantine_bucket - role = google_project_iam_custom_role.promote_and_quarantine_bucket_role.name - members = [ - "serviceAccount:${google_service_account.service_account.email}", - ] - depends_on = [ - google_project_iam_custom_role.promote_and_quarantine_bucket_role - ] +resource "google_storage_bucket_iam_member" "binding_quarantine_bucket" { + count = local.quarantine_enabled != "" ? 1 : 0 + bucket = var.quarantine_bucket + role = google_project_iam_custom_role.quarantine_bucket_role[0].id + member = "serviceAccount:${google_service_account.service_account.email}" + provider = google.quarantine_provider } resource "google_storage_bucket_iam_binding" "binding_scanning_bucket" { bucket = var.scanning_bucket - role = google_project_iam_custom_role.scanning_bucket_access_role.name + role = google_project_iam_custom_role.scanning_bucket_access_role.name members = [ "serviceAccount:${google_service_account.service_account.email}", ] @@ -92,44 +91,44 @@ resource "google_storage_bucket_iam_binding" "binding_scanning_bucket" { } resource "google_storage_bucket" "artifacts_bucket" { - name = "artifacts-promote-and-quarantine-plugin-${lower(random_id.deploy_suffix.hex)}" - location = var.region - project = var.project_id + name = "artifacts-promote-and-quarantine-plugin-${lower(random_id.deploy_suffix.hex)}" + location = var.region + project = var.project_id uniform_bucket_level_access = true - force_destroy = true + force_destroy = true } resource "google_storage_bucket_object" "archive" { - name = "gcp-promote-and-quarantine-plugin.zip" - bucket = google_storage_bucket.artifacts_bucket.name - source = data.archive_file.source.output_path + name = "gcp-promote-and-quarantine-plugin.zip" + bucket = google_storage_bucket.artifacts_bucket.name + source = data.archive_file.source.output_path content_type = "application/zip" - depends_on = [ + depends_on = [ google_storage_bucket.artifacts_bucket, data.archive_file.source ] } resource "google_cloudfunctions_function" "promote_and_quarantining_plugin" { - name = "${var.plugin_prefix}-promote-and-quarantine-${random_id.deploy_suffix.hex}" - description = "Promote and Quarantine plugin ${random_id.deploy_suffix.hex}" + name = "${var.plugin_prefix}-promote-and-quarantine-${random_id.deploy_suffix.hex}" + description = "Promote and Quarantine plugin ${random_id.deploy_suffix.hex}" source_archive_bucket = google_storage_bucket.artifacts_bucket.name source_archive_object = google_storage_bucket_object.archive.name - runtime = "python312" - entry_point = "main" - project = var.project_id + runtime = "python312" + entry_point = "main" + project = var.project_id event_trigger { event_type = "providers/cloud.pubsub/eventTypes/topic.publish" - resource = "projects/${var.project_id}/topics/${var.scan_result_topic}" + resource = "projects/${var.project_id}/topics/${var.scan_result_topic}" } environment_variables = { QUARANTINE_STORAGE_BUCKET = var.quarantine_bucket - QUARANTINE_MODE = var.quarantine_mode - PROMOTE_STORAGE_BUCKET = var.promote_bucket - PROMOTE_MODE = var.promote_mode + QUARANTINE_MODE = var.quarantine_mode + PROMOTE_STORAGE_BUCKET = var.promote_bucket + PROMOTE_MODE = var.promote_mode } service_account_email = google_service_account.service_account.email diff --git a/post-scan-actions/gcp-python-promote-or-quarantine/provider.tf b/post-scan-actions/gcp-python-promote-or-quarantine/provider.tf new file mode 100644 index 0000000..5ab2394 --- /dev/null +++ b/post-scan-actions/gcp-python-promote-or-quarantine/provider.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.11.0" + } + } +} + +provider "google" { + project = var.project_id + region = var.region +} + +provider "google" { + alias = "quarantine_provider" + project = var.quarantine_bucket_properties.project_id != "" ? var.quarantine_bucket_properties.project_id : var.project_id + region = var.quarantine_bucket_properties.region != "" ? var.quarantine_bucket_properties.region : var.region +} + +provider "google" { + alias = "promote_provider" + project = var.promote_bucket_properties.project_id != "" ? var.promote_bucket_properties.project_id : var.project_id + region = var.promote_bucket_properties.region != "" ? var.promote_bucket_properties.region : var.region +} diff --git a/post-scan-actions/gcp-python-promote-or-quarantine/src/requirements.txt b/post-scan-actions/gcp-python-promote-or-quarantine/src/requirements.txt index 62bb53e..cde8679 100644 --- a/post-scan-actions/gcp-python-promote-or-quarantine/src/requirements.txt +++ b/post-scan-actions/gcp-python-promote-or-quarantine/src/requirements.txt @@ -1 +1 @@ -google-cloud-storage==2.14.0 +google-cloud-storage==2.16.0 diff --git a/post-scan-actions/gcp-python-promote-or-quarantine/variables.tf b/post-scan-actions/gcp-python-promote-or-quarantine/variables.tf index 28085cc..24061f4 100644 --- a/post-scan-actions/gcp-python-promote-or-quarantine/variables.tf +++ b/post-scan-actions/gcp-python-promote-or-quarantine/variables.tf @@ -1,61 +1,83 @@ -variable "project_id" { - type = string - description = "ID of the GCP project which the plugin will be deployed" - sensitive = true -} - -variable "region" { - type = string - description = "GCP region to deploy the plugin" -} - -variable "plugin_prefix" { - type = string - description = "GCP function prefix to use for the plugin" -} - -variable "deployment_name" { - type = string - description = "The name of the deployment" -} - -variable "scan_result_topic" { - type = string - description = "The name of the Pub/Sub topic for scan results topic" -} - -variable "scanning_bucket" { - type = string - description = "Scanning bucket name" - nullable = false -} - -variable "quarantine_mode" { - type = string - description = "The quarantine mode to use: 'move' or 'copy'" - nullable = false - validation { - condition = contains(["move", "copy"], var.quarantine_mode) - error_message = "Value must be one of 'move' or 'copy'." - } -} - -variable "quarantine_bucket" { - type = string - description = "The quarantine bucket to use. Leave it empty if you don't want to quarantine files." -} - -variable "promote_mode" { - type = string - description = "The promote mode to use: 'move' or 'copy'" - nullable = false - validation { - condition = contains(["move", "copy"], var.promote_mode) - error_message = "Value must be one of 'move' or 'copy'." - } -} - -variable "promote_bucket" { - type = string - description = "The promote bucket to use. Leave it empty if you don't want to promote files." -} +variable "project_id" { + type = string + description = "ID of the GCP project which the plugin will be deployed" + sensitive = true +} + +variable "region" { + type = string + description = "GCP region to deploy the plugin" +} + +variable "plugin_prefix" { + type = string + description = "GCP function prefix to use for the plugin" +} + +variable "deployment_name" { + type = string + description = "The name of the deployment" +} + +variable "scan_result_topic" { + type = string + description = "The name of the Pub/Sub topic for scan results topic" +} + +variable "scanning_bucket" { + type = string + description = "Scanning bucket name" + nullable = false +} + +variable "quarantine_mode" { + type = string + description = "The quarantine mode to use: 'move' or 'copy'" + nullable = false + validation { + condition = contains(["move", "copy"], var.quarantine_mode) + error_message = "Value must be one of 'move' or 'copy'." + } + default = "move" +} + +variable "quarantine_bucket" { + type = string + description = "The quarantine bucket to use. Leave it empty if you don't want to quarantine files." + nullable = true + default = "" +} + +variable "quarantine_bucket_properties" { + type = object({ + project_id = string + region = string + }) + description = "The properties of the quarantine bucket including the following: gcp project, location used." +} + +variable "promote_mode" { + type = string + description = "The promote mode to use: 'move' or 'copy'" + nullable = false + validation { + condition = contains(["move", "copy"], var.promote_mode) + error_message = "Value must be one of 'move' or 'copy'." + } + default = "move" +} + +variable "promote_bucket" { + type = string + description = "The promote bucket to use. Leave it empty if you don't want to promote files." + nullable = true + default = "" +} + +variable "promote_bucket_properties" { + type = object({ + project_id = string + region = string + }) + description = "The properties of the promote bucket including the following: gcp project, location used." +}