Skip to content

Commit 795fbe3

Browse files
committed
feat: GCP promote and quarantine add support for cross project
1 parent c3d48db commit 795fbe3

File tree

6 files changed

+179
-120
lines changed

6 files changed

+179
-120
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
main.auto.tfvars

post-scan-actions/gcp-python-promote-or-quarantine/main.auto.tfvars.example

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,19 @@ deployment_name = "<DEPLOYMENT_NAME>" // e.g. test-deployment
66

77
scan_result_topic = "<TOPIC_NAME>" // e.g. my-deployment-scan-result-topic
88
scanning_bucket = "<SCANNING_BUCKET_NAME>" // e.g. scanning-gcs-bucket
9-
quarantine_mode = "move" // move or copy leave it empty
9+
10+
// quarantine settings
11+
quarantine_mode = "move" // move or copy. default is move.
1012
quarantine_bucket = "<QUARANTINE_BUCKET_NAME>" // e.g. quarantine-gcs-bucket Leave it empty if you don't want to quarantine files.
11-
promote_mode = "move" // move or copy
13+
quarantine_bucket_properties = { // additional properties for the quarantine bucket used when cross project or cross region is needed.
14+
region = "<QUARANTINE_BUCKET_GCP_REGION>" // e.g. us-central1
15+
project_id = "<QUARANTINE_BUCKET_GCP_PROJECT_ID>" // e.g. test-project-998877
16+
}
17+
18+
// promote settings
19+
promote_mode = "move" // move or copy. default is move.
1220
promote_bucket = "<PROMOTE_BUCKET_NAME>" // e.g. promote-gcs-bucket Leave it empty if you don't want to promote files.
21+
promote_bucket_properties = { // additional properties for the promote bucket used when cross project or cross region is needed.
22+
region = "<PROMOTE_BUCKET_GCP_REGION>" // e.g. us-central1
23+
project_id = "<PROMOTE_BUCKET_GCP_PROJECT>" // e.g. test-project-998877
24+
}

post-scan-actions/gcp-python-promote-or-quarantine/main.tf

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1-
terraform {
2-
required_providers {
3-
google = {
4-
source = "hashicorp/google"
5-
version = "~> 5.11.0"
6-
}
7-
}
8-
}
9-
10-
provider "google" {
11-
project = var.project_id
12-
region = var.region
1+
locals {
2+
promote_enabled = var.promote_bucket != ""
3+
quarantine_enabled = var.quarantine_bucket != ""
134
}
145

156
resource "random_id" "deploy_suffix" {
@@ -28,61 +19,69 @@ data "archive_file" "source" {
2819
}
2920

3021
resource "google_service_account" "service_account" {
31-
account_id = "qua-pro-plugin-sa-${lower(random_id.deploy_suffix.hex)}"
32-
display_name = "Quarantine/Promote plugin Service Account ${random_id.deploy_suffix.hex}"
33-
project = var.project_id
22+
account_id = "qua-pro-plugin-sa-${lower(random_id.deploy_suffix.hex)}"
23+
display_name = "TM FSS Quarantine/Promote plugin Service Account ${random_id.deploy_suffix.hex}"
24+
project = var.project_id
3425
}
3526

36-
resource "google_project_iam_custom_role" "promote_and_quarantine_bucket_role" {
37-
role_id = "plugin_storage_bucket_write_${lower(random_id.deploy_suffix.hex)}"
38-
title = "Promote/Quarantine Bucket Write ${random_id.deploy_suffix.hex}"
27+
resource "google_project_iam_custom_role" "promote_bucket_role" {
28+
count = local.promote_enabled ? 1 : 0
29+
role_id = "promote_bucket_write_${lower(random_id.deploy_suffix.hex)}"
30+
title = "Promote Bucket Write ${random_id.deploy_suffix.hex}"
3931
permissions = [
4032
"storage.objects.create",
4133
"storage.objects.delete",
4234
"storage.objects.update"
4335
]
36+
provider = google.promote_provider
37+
}
38+
39+
resource "google_project_iam_custom_role" "quarantine_bucket_role" {
40+
count = local.quarantine_enabled ? 1 : 0
41+
role_id = "quarantine_bucket_write_${lower(random_id.deploy_suffix.hex)}"
42+
title = "Quarantine Bucket Write ${random_id.deploy_suffix.hex}"
43+
permissions = [
44+
"storage.objects.create",
45+
"storage.objects.delete",
46+
"storage.objects.update"
47+
]
48+
provider = google.quarantine_provider
4449
}
4550

4651
resource "google_project_iam_custom_role" "scanning_bucket_access_role" {
4752
role_id = "plugin_storage_bucket_access_${lower(random_id.deploy_suffix.hex)}"
48-
title = "Scanning Bucket Access ${random_id.deploy_suffix.hex}"
53+
title = "Scanning Bucket Access ${random_id.deploy_suffix.hex}"
4954
permissions = var.promote_mode == "move" || var.quarantine_mode == "move" ? [
5055
"storage.objects.delete",
5156
"storage.objects.get",
5257
"storage.objects.update"
53-
] : [
58+
] : [
5459
"storage.objects.get",
5560
"storage.objects.update"
5661
]
62+
project = var.project_id
63+
provider = google
5764
}
5865

59-
resource "google_storage_bucket_iam_binding" "binding_promote_bucket" {
60-
count = var.promote_bucket != "" ? 1 : 0
66+
resource "google_storage_bucket_iam_member" "binding_promote_bucket" {
67+
count = local.promote_enabled != "" ? 1 : 0
6168
bucket = var.promote_bucket
62-
role = google_project_iam_custom_role.promote_and_quarantine_bucket_role.name
63-
members = [
64-
"serviceAccount:${google_service_account.service_account.email}",
65-
]
66-
depends_on = [
67-
google_project_iam_custom_role.promote_and_quarantine_bucket_role
68-
]
69+
role = google_project_iam_custom_role.promote_bucket_role[0].id
70+
member = "serviceAccount:${google_service_account.service_account.email}"
71+
provider = google.promote_provider
6972
}
7073

71-
resource "google_storage_bucket_iam_binding" "binding_quarantine_bucket" {
72-
count = var.quarantine_bucket != "" ? 1 : 0
74+
resource "google_storage_bucket_iam_member" "binding_quarantine_bucket" {
75+
count = local.quarantine_enabled != "" ? 1 : 0
7376
bucket = var.quarantine_bucket
74-
role = google_project_iam_custom_role.promote_and_quarantine_bucket_role.name
75-
members = [
76-
"serviceAccount:${google_service_account.service_account.email}",
77-
]
78-
depends_on = [
79-
google_project_iam_custom_role.promote_and_quarantine_bucket_role
80-
]
77+
role = google_project_iam_custom_role.quarantine_bucket_role[0].id
78+
member = "serviceAccount:${google_service_account.service_account.email}"
79+
provider = google.quarantine_provider
8180
}
8281

8382
resource "google_storage_bucket_iam_binding" "binding_scanning_bucket" {
8483
bucket = var.scanning_bucket
85-
role = google_project_iam_custom_role.scanning_bucket_access_role.name
84+
role = google_project_iam_custom_role.scanning_bucket_access_role.name
8685
members = [
8786
"serviceAccount:${google_service_account.service_account.email}",
8887
]
@@ -92,44 +91,44 @@ resource "google_storage_bucket_iam_binding" "binding_scanning_bucket" {
9291
}
9392

9493
resource "google_storage_bucket" "artifacts_bucket" {
95-
name = "artifacts-promote-and-quarantine-plugin-${lower(random_id.deploy_suffix.hex)}"
96-
location = var.region
97-
project = var.project_id
94+
name = "artifacts-promote-and-quarantine-plugin-${lower(random_id.deploy_suffix.hex)}"
95+
location = var.region
96+
project = var.project_id
9897
uniform_bucket_level_access = true
99-
force_destroy = true
98+
force_destroy = true
10099
}
101100

102101
resource "google_storage_bucket_object" "archive" {
103-
name = "gcp-promote-and-quarantine-plugin.zip"
104-
bucket = google_storage_bucket.artifacts_bucket.name
105-
source = data.archive_file.source.output_path
102+
name = "gcp-promote-and-quarantine-plugin.zip"
103+
bucket = google_storage_bucket.artifacts_bucket.name
104+
source = data.archive_file.source.output_path
106105
content_type = "application/zip"
107106

108-
depends_on = [
107+
depends_on = [
109108
google_storage_bucket.artifacts_bucket,
110109
data.archive_file.source
111110
]
112111
}
113112

114113
resource "google_cloudfunctions_function" "promote_and_quarantining_plugin" {
115-
name = "${var.plugin_prefix}-promote-and-quarantine-${random_id.deploy_suffix.hex}"
116-
description = "Promote and Quarantine plugin ${random_id.deploy_suffix.hex}"
114+
name = "${var.plugin_prefix}-promote-and-quarantine-${random_id.deploy_suffix.hex}"
115+
description = "Promote and Quarantine plugin ${random_id.deploy_suffix.hex}"
117116
source_archive_bucket = google_storage_bucket.artifacts_bucket.name
118117
source_archive_object = google_storage_bucket_object.archive.name
119-
runtime = "python312"
120-
entry_point = "main"
121-
project = var.project_id
118+
runtime = "python312"
119+
entry_point = "main"
120+
project = var.project_id
122121

123122
event_trigger {
124123
event_type = "providers/cloud.pubsub/eventTypes/topic.publish"
125-
resource = "projects/${var.project_id}/topics/${var.scan_result_topic}"
124+
resource = "projects/${var.project_id}/topics/${var.scan_result_topic}"
126125
}
127126

128127
environment_variables = {
129128
QUARANTINE_STORAGE_BUCKET = var.quarantine_bucket
130-
QUARANTINE_MODE = var.quarantine_mode
131-
PROMOTE_STORAGE_BUCKET = var.promote_bucket
132-
PROMOTE_MODE = var.promote_mode
129+
QUARANTINE_MODE = var.quarantine_mode
130+
PROMOTE_STORAGE_BUCKET = var.promote_bucket
131+
PROMOTE_MODE = var.promote_mode
133132
}
134133

135134
service_account_email = google_service_account.service_account.email
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
terraform {
2+
required_providers {
3+
google = {
4+
source = "hashicorp/google"
5+
version = "~> 5.11.0"
6+
}
7+
}
8+
}
9+
10+
provider "google" {
11+
project = var.project_id
12+
region = var.region
13+
}
14+
15+
provider "google" {
16+
alias = "quarantine_provider"
17+
project = var.quarantine_bucket_properties.project_id != "" ? var.quarantine_bucket_properties.project_id : var.project_id
18+
region = var.quarantine_bucket_properties.region != "" ? var.quarantine_bucket_properties.region : var.region
19+
}
20+
21+
provider "google" {
22+
alias = "promote_provider"
23+
project = var.promote_bucket_properties.project_id != "" ? var.promote_bucket_properties.project_id : var.project_id
24+
region = var.promote_bucket_properties.region != "" ? var.promote_bucket_properties.region : var.region
25+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
google-cloud-storage==2.14.0
1+
google-cloud-storage==2.16.0
Lines changed: 83 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,83 @@
1-
variable "project_id" {
2-
type = string
3-
description = "ID of the GCP project which the plugin will be deployed"
4-
sensitive = true
5-
}
6-
7-
variable "region" {
8-
type = string
9-
description = "GCP region to deploy the plugin"
10-
}
11-
12-
variable "plugin_prefix" {
13-
type = string
14-
description = "GCP function prefix to use for the plugin"
15-
}
16-
17-
variable "deployment_name" {
18-
type = string
19-
description = "The name of the deployment"
20-
}
21-
22-
variable "scan_result_topic" {
23-
type = string
24-
description = "The name of the Pub/Sub topic for scan results topic"
25-
}
26-
27-
variable "scanning_bucket" {
28-
type = string
29-
description = "Scanning bucket name"
30-
nullable = false
31-
}
32-
33-
variable "quarantine_mode" {
34-
type = string
35-
description = "The quarantine mode to use: 'move' or 'copy'"
36-
nullable = false
37-
validation {
38-
condition = contains(["move", "copy"], var.quarantine_mode)
39-
error_message = "Value must be one of 'move' or 'copy'."
40-
}
41-
}
42-
43-
variable "quarantine_bucket" {
44-
type = string
45-
description = "The quarantine bucket to use. Leave it empty if you don't want to quarantine files."
46-
}
47-
48-
variable "promote_mode" {
49-
type = string
50-
description = "The promote mode to use: 'move' or 'copy'"
51-
nullable = false
52-
validation {
53-
condition = contains(["move", "copy"], var.promote_mode)
54-
error_message = "Value must be one of 'move' or 'copy'."
55-
}
56-
}
57-
58-
variable "promote_bucket" {
59-
type = string
60-
description = "The promote bucket to use. Leave it empty if you don't want to promote files."
61-
}
1+
variable "project_id" {
2+
type = string
3+
description = "ID of the GCP project which the plugin will be deployed"
4+
sensitive = true
5+
}
6+
7+
variable "region" {
8+
type = string
9+
description = "GCP region to deploy the plugin"
10+
}
11+
12+
variable "plugin_prefix" {
13+
type = string
14+
description = "GCP function prefix to use for the plugin"
15+
}
16+
17+
variable "deployment_name" {
18+
type = string
19+
description = "The name of the deployment"
20+
}
21+
22+
variable "scan_result_topic" {
23+
type = string
24+
description = "The name of the Pub/Sub topic for scan results topic"
25+
}
26+
27+
variable "scanning_bucket" {
28+
type = string
29+
description = "Scanning bucket name"
30+
nullable = false
31+
}
32+
33+
variable "quarantine_mode" {
34+
type = string
35+
description = "The quarantine mode to use: 'move' or 'copy'"
36+
nullable = false
37+
validation {
38+
condition = contains(["move", "copy"], var.quarantine_mode)
39+
error_message = "Value must be one of 'move' or 'copy'."
40+
}
41+
default = "move"
42+
}
43+
44+
variable "quarantine_bucket" {
45+
type = string
46+
description = "The quarantine bucket to use. Leave it empty if you don't want to quarantine files."
47+
nullable = true
48+
default = ""
49+
}
50+
51+
variable "quarantine_bucket_properties" {
52+
type = object({
53+
project_id = string
54+
region = string
55+
})
56+
description = "The properties of the quarantine bucket including the following: gcp project, location, CMEK used."
57+
}
58+
59+
variable "promote_mode" {
60+
type = string
61+
description = "The promote mode to use: 'move' or 'copy'"
62+
nullable = false
63+
validation {
64+
condition = contains(["move", "copy"], var.promote_mode)
65+
error_message = "Value must be one of 'move' or 'copy'."
66+
}
67+
default = "move"
68+
}
69+
70+
variable "promote_bucket" {
71+
type = string
72+
description = "The promote bucket to use. Leave it empty if you don't want to promote files."
73+
nullable = true
74+
default = ""
75+
}
76+
77+
variable "promote_bucket_properties" {
78+
type = object({
79+
project_id = string
80+
region = string
81+
})
82+
description = "The properties of the promote bucket including the following: gcp project, location, CMEK used."
83+
}

0 commit comments

Comments
 (0)