Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Add GCP Full scan and schedule scan plugin #178

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"version": "0.2",
"allowCompoundWords": true,
"ignorePaths": [],
"ignorePaths": [
"yarn.lock"
],
"ignoreRegExpList": [
":.*:",
"arn:.*"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const { nodeExternalsPlugin } = require('esbuild-node-externals')
const rimraf = require('rimraf')
const fs = require('fs')
const path = require('path')
const archiver = require('archiver')

const OUT_DIR = 'dist'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
artifact.zip
54 changes: 54 additions & 0 deletions scan-triggers/gcp-nodejs-bucket-full-and-scheduled-scan/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Cloud One File Storage Security Scan Trigger - GCP Full Scan and Scheduled Scan

This plugin is design to perform full scan and schedule scan on GCP cloud storage.

## Prerequest

1. Install File storage security in you GCP environment
1. [Terraform](https://developer.hashicorp.com/terraform/install) (Not needed for cloud shell.)

## Installation

### Using GCP Cloud Shell

[![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.svg)](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Ftrendmicro%2Fcloudone-filestorage-plugins&cloudshell_workspace=scan-triggers%2Fgcp-nodejs-bucket-full-and-scheduled-scan&cloudshell_tutorial=docs%2Ftutorial.md)

### Local machine

1. Initialize terraform

```bash
terraform init
```

1. Deploy the function and fill the variables following the CLI. (Or using the `main.auto.tfvars` file)

```sh
terraform apply
```

Instead of filling in the variables individually, you can create and use a `main.auto.tfvars` file. Enter the variables in to the `main.auto.tfvars.example` file, and then save the file as `main.auto.tfvars`. Once you have created and saved the file, you can reuse the file rather than fill in the variables every time.

1. Remember to save the `terraform.tfstate` file.

### Variables

- **deployment_name**: Name of the deployment. This is used to generate unique suffix for resources created by the plugin.
- **project_id**: GCP project ID which the plugin will be deployed.
- **region**: GCP region to deploy the plugin.
- **scanner_pubsub_topic_project**: GCP project ID which the scanner Pub/Sub topic is deployed. This value can be found in the FSS scanner deploy output **scannerProjectID**.
- **scanner_pubsub_topic**: Scanner Pub/Sub topic name. This value can be found in the FSS scanner deployment output **scannerTopic**.
- **scan_result_topic**: Scan result Pub/Sub topic name. This value can be found in the FSS storage deployment output **scanResultTopic**.
- **scanning_bucket_name**: GCS bucket to perform schedule scan on.
- **schedular_settings**: Settings for the cloud scheduler trigger for workflow. Default to run on every monday at 12:00 AM UTC.
- **trend_micro_fss_bucket_listener_role_id**: Reused custom role used by the bucketListener function to create presigned URL. This value can be found in IAM console page with title `trend-micro-fss-bucket-listener-role`.

## Test plugin

1. Find the deployed workflow. Workflow name can be found in the terraform output **workflow_name**.

1. Execute workflow using the following argument.

```json
{ "bucketName": "<SCANNING_BUCKET_NAME>" }
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Cloud One File Storage Security Full scan and schedule scan plugin for GCP

## Overview

<walkthrough-tutorial-duration duration="10"></walkthrough-tutorial-duration>

This tutorial will guide you to deploy the full scan and schedule scan plugin.

## Project Setup

Copy the execute the script below to select the project where the storage stack is deployed.

<walkthrough-project-setup></walkthrough-project-setup>

```sh
gcloud config set project <walkthrough-project-id/>
```

## Deploy full scan and schedule scan plugin

1. Initialize terraform.

```sh
terraform init
```

1. Deploy the resources and fill the variables following the CLI. (Or using the `main.auto.tfvars` file)

```sh
terraform apply
```

Instead of filling in the variables individually, you can create and use a `main.auto.tfvars` file. Enter the variables in to the `main.auto.tfvars.example` file, and then save the file as `main.auto.tfvars`. Once you have created and saved the file, you can reuse the file rather than fill in the variables every time.

1. Remember to save the `terraform.tfstate` file.

### Variables

- **deployment_name**: Name of the deployment. This is used to generate unique suffix for resources created by the plugin.
- **project_id**: GCP project ID which the plugin will be deployed.
- **region**: GCP region to deploy the plugin.
- **scanner_pubsub_topic_project**: GCP project ID which the scanner Pub/Sub topic is deployed. This value can be found in the FSS scanner deploy output **scannerProjectID**.
- **scanner_pubsub_topic**: Scanner Pub/Sub topic name. This value can be found in the FSS scanner deployment output **scannerTopic**.
- **scan_result_topic**: Scan result Pub/Sub topic name. This value can be found in the FSS storage deployment output **scanResultTopic**.
- **scanning_bucket_name**: GCS bucket to perform schedule scan on.
- **schedular_settings**: Settings for the cloud scheduler trigger for workflow. Default to run on every monday at 12:00 AM UTC.
- **trend_micro_fss_bucket_listener_role_id**: Reused custom role used by the bucketListener function to create presigned URL. This value can be found in IAM console page with title `trend-micro-fss-bucket-listener-role`.

## Test plugin

1. Find the deployed workflow. Workflow name can be found in the terraform output **workflow_name**.

1. Execute workflow using the following argument.

```json
{ "bucketName": "<SCANNING_BUCKET_NAME>" }
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
deployment_name = "<DEPLOYMENT_NAME>"
project_id = "<GCP_PROJECT_ID>"
region = "<GCP_REGION>"

scanner_pubsub_topic_project = "<SCANNER_PUBSUB_TOPIC_GCP_PROJECT_ID>"
scanner_pubsub_topic = "<SCANNER_PUBSUB_TOPIC>"
scan_result_topic = "<SCAN_RESULT_TOPIC>"

scanning_bucket_name = "<SCANNING_BUCKET_NAME>"

schedular_settings = {
cron = "0 0 * * 1"
timezone = "Etc/UTC"
}

trend_micro_fss_bucket_listener_role_id = "<BUCKET_LISTENER_ROLE_ID>"
111 changes: 111 additions & 0 deletions scan-triggers/gcp-nodejs-bucket-full-and-scheduled-scan/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
locals {
services = [
"artifactregistry.googleapis.com",
"cloudbuild.googleapis.com",
"cloudscheduler.googleapis.com",
"cloudtasks.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
"run.googleapis.com",
"storage.googleapis.com",
"workflows.googleapis.com",
]
}

resource "google_project_service" "enable_apis" {
for_each = toset(local.services)
service = each.value
disable_on_destroy = false
}

resource "random_id" "deploy_suffix" {
keepers = {
# Generate a new suffix each time we switch to a new deployment
deployment_name = "${var.deployment_name}"
}

byte_length = 3
}

resource "google_project_iam_custom_role" "workflow_custom_role" {
role_id = "tmfssfsplwf${lower(random_id.deploy_suffix.hex)}"
title = "TM C1FSS fullscan and schedule scan workflow custom role"
permissions = [
"iam.serviceAccounts.actAs"
]
project = var.project_id
}

module "function_sa" {
source = "./modules/iam"
id = "tmfss-st-sa${lower(random_id.deploy_suffix.hex)}"
name = "tmfss-st-sa"
roles = {
readObejctRole = {
name = "roles/storage.objectViewer"
project = var.project_id
}
messagePublishRole = {
name = "roles/pubsub.publisher"
project = var.scanner_pubsub_topic_project
}
signObjectRole = {
name = var.trend_micro_fss_bucket_listener_role_id
project = var.project_id
}
}
description = "Service account for C1FSS fullscan and schedule scan plugin cloud function"
}

module "workflow_sa" {
source = "./modules/iam"
id = "tmfss-wf-sa-${lower(random_id.deploy_suffix.hex)}"
name = "tmfss-wf-sa"
roles = {
listObjectsRole = {
name = "roles/storage.objectViewer"
project = var.project_id
}
functionTriggerRole = {
name = "roles/run.invoker"
project = var.project_id
}
workflowTriggerRole = {
name = "roles/workflows.invoker"
project = var.project_id
}
cloudTaskCreateRole = {
name = "roles/cloudtasks.enqueuer"
project = var.project_id
}
customRole = {
name = google_project_iam_custom_role.workflow_custom_role.name
project = var.project_id
}
}
description = "Service account for C1FSS fullscan and schedule scan plugin workflow"
depends_on = [module.function_sa]
}

module "function" {
source = "./modules/cloudfunctions"
service_account_email = module.function_sa.service_account_email
deployment_name = var.deployment_name
project_id = var.project_id
region = var.region
scan_result_topic = var.scan_result_topic
scanner_pubsub_topic_project = var.scanner_pubsub_topic_project
scanner_pubsub_topic = var.scanner_pubsub_topic
suffix = lower(random_id.deploy_suffix.hex)
}

module "workflow" {
source = "./modules/workflow"
project_id = var.project_id
region = var.region
service_account = module.workflow_sa.service_account_email
schedular_settings = var.schedular_settings
scanning_bucket_name = var.scanning_bucket_name
scan_trigger_function_url = module.function.cloudfunction_url
suffix = lower(random_id.deploy_suffix.hex)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
locals {
source_files = [
"${path.root}/src/index.js",
"${path.root}/package.json",
"${path.root}/yarn.lock"
]
project = var.project_id
}

resource "google_storage_bucket" "function_artifact_bucket" {
name = "tmfss-fullscan-artifact"
location = var.region
uniform_bucket_level_access = true
}

data "archive_file" "function_artifact" {
type = "zip"
output_path = "${path.root}/artifact.zip"
source {
content = file(local.source_files[0])
filename = "src/${basename(local.source_files[0])}"
}

source {
content = file(local.source_files[1])
filename = basename(local.source_files[1])
}

source {
content = file(local.source_files[2])
filename = basename(local.source_files[2])
}
}

resource "google_storage_bucket" "bucket" {
name = "${local.project}-gcf-source-${var.suffix}" # Every bucket name must be globally unique
location = var.region
uniform_bucket_level_access = true
}

resource "google_storage_bucket_object" "object" {
name = "artifact.zip"
bucket = google_storage_bucket.bucket.name
source = data.archive_file.function_artifact.output_path
}

resource "google_cloudfunctions2_function" "function" {
name = "tmfss-fs-pl-st-${var.suffix}"
location = var.region
description = "TM C1 FSS Fullscan and schedule scan scan trigger function"

build_config {
runtime = "nodejs20"
entry_point = "handler"
source {
storage_source {
bucket = google_storage_bucket.bucket.name
object = google_storage_bucket_object.object.name
}
}
}

service_config {
service_account_email = var.service_account_email
environment_variables = {
"SCANNER_PUBSUB_TOPIC" : var.scanner_pubsub_topic
"SCANNER_PROJECT_ID" : var.scanner_pubsub_topic_project
"SCAN_RESULT_TOPIC" : var.scan_result_topic
"DEPLOYMENT_NAME" : var.deployment_name
"REPORT_OBJECT_KEY" : var.report_object_key
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "cloudfunction_name" {
value = google_cloudfunctions2_function.function.name
}

output "cloudfunction_id" {
value = google_cloudfunctions2_function.function.id
}

output "cloudfunction_url" {
value = google_cloudfunctions2_function.function.url
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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 "service_account_email" {
type = string
description = "Email of the service account which cloud function will used."
}

variable "scanner_pubsub_topic" {
type = string
description = "Pub/Sub topic to trigger scanner."
}

variable "scanner_pubsub_topic_project" {
type = string
description = "Scanner Pub/Sub topic gcp project."
}

variable "scan_result_topic" {
type = string
description = "Scan result Pub/Sub topic."
}

variable "deployment_name" {
type = string
description = "The name of the deployment. This is used to generate unique suffix for some resource."
}

variable "report_object_key" {
type = bool
default = false
description = "If true, the report object key will be used instead of sha256."
}

variable "suffix" {
type = string
description = "Suffix to be appended to the resources."
}
Loading