Skip to content
4 changes: 4 additions & 0 deletions modules/services/workload-scan/provider.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ terraform {
source = "hashicorp/random"
version = ">= 3.1, < 4.0"
}
sysdig = {
source = "sysdiglabs/sysdig"
version = "~> 1.37"
}
}
}
66 changes: 66 additions & 0 deletions modules/vm-workload-scanning/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# GCP VM Workload Scanning Module

This Module creates the resources required to perform agentless workload scanning operations in Google Cloud Platform (GCP). It sets up the necessary roles, service accounts, and workload identity providers to enable Sysdig to scan workloads running in GCP projects.

By default, it will create a service account with permissions necessary to access and access GAR and GCR repositories and pull their images.

The following resources will be created in each instrumented project:
- A Service Account and associated roles that allow Sysdig to perform tasks necessary for VM agentless workload scanning, i.e., access GAR/GCR repositories and pull its images.
- A Workload Identity Provider to facilitate secure authentication between GCP and Sysdig.

### Requirements

| Name | Version |
|------|---------|
| terraform | ~> 1.7 |
| google | >= 4.50.0 |
| sysdig | ~> 1.37 |

### Providers

| Name | Version |
|------|---------|
| google | >= 4.50.0 |
| sysdig | ~> 1.37 |

### Modules

No modules.

### Resources

| Name | Type |
|------|------|
| google_service_account.controller | resource |
| google_project_iam_member.controller | resource |
| google_iam_workload_identity_pool.agentless | resource |
| google_iam_workload_identity_pool_provider.agentless | resource |
| google_iam_workload_identity_pool.agentless_gcp | resource |
| google_iam_workload_identity_pool_provider.agentless_gcp | resource |
| google_project.project | data source |

### Inputs

| Name | Description | Type | Default | Required |
|------|----------------------------------------------------------------------------------------------------------------------------------|------|---------|:--------:|
| project_id | GCP Project ID | string | n/a | yes |
| is_organizational | Set this field to 'true' to deploy workload scanning to a GCP Organization. | bool | false | no |
| organization_domain | (Optional) Organization domain. e.g. sysdig.com | string | "" | no |
| role_name | Name for the Worker Role on the Customer infrastructure | string | "SysdigAgentlessWorkloadRole" | no |
| sysdig_secure_account_id | ID of the Sysdig Cloud Account to enable VM Workload Scanning for (in case of organization, ID of the Sysdig management account) | string | n/a | yes |

### Outputs

| Name | Description |
|------|-------------|
| vm_workload_scanning_component_id | Component identifier of service principal created in Sysdig Backend for VM Workload Scanning |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## Authors

Module is maintained by [Sysdig](https://sysdig.com).

## License

Apache 2 Licensed. See LICENSE for full details.
112 changes: 112 additions & 0 deletions modules/vm-workload-scanning/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
locals {
suffix = random_id.suffix.hex
}

resource "random_id" "suffix" {
byte_length = 3
}

data "google_project" "project" {
project_id = var.project_id
}

data "sysdig_secure_trusted_cloud_identity" "trusted_identity" {
cloud_provider = "gcp"
}

data "sysdig_secure_tenant_external_id" "external_id" {}

resource "google_service_account" "controller" {
project = var.project_id
account_id = "sysdig-ws-${local.suffix}"
display_name = "Sysdig Agentless Workload Scanning"
}

resource "google_project_iam_custom_role" "controller" {
project = var.project_id
role_id = "${var.role_name}WorkloadController${title(local.suffix)}"
title = "Role for Sysdig Agentless Workload Controller"
permissions = [
# artifact registry reader permissions
"artifactregistry.repositories.downloadArtifacts",
"artifactregistry.repositories.get",
"artifactregistry.repositories.list",
"artifactregistry.dockerimages.get",
"artifactregistry.dockerimages.list",
"storage.objects.get",
"storage.buckets.list",
"storage.objects.list",

# workload identity federation
"iam.serviceAccounts.getAccessToken",
]
}

resource "google_project_iam_binding" "controller_binding" {
project = var.project_id
role = google_project_iam_custom_role.controller.id

members = [
"serviceAccount:${google_service_account.controller.email}",
]
}

resource "google_iam_workload_identity_pool" "agentless" {
workload_identity_pool_id = "sysdig-wl-${local.suffix}"
}

resource "google_iam_workload_identity_pool_provider" "agentless" {
project = var.project_id
workload_identity_pool_id = google_iam_workload_identity_pool.agentless.workload_identity_pool_id
workload_identity_pool_provider_id = "sysdig-wl-${local.suffix}"
display_name = "Sysdig Workload Controller"
description = "AWS identity pool provider for Sysdig Secure Agentless Workload Scanning"
disabled = false

attribute_condition = "attribute.aws_role==\"arn:aws:sts::${data.sysdig_secure_trusted_cloud_identity.trusted_identity.aws_account_id}:assumed-role/${data.sysdig_secure_trusted_cloud_identity.trusted_identity.aws_role_name}/${data.sysdig_secure_tenant_external_id.external_id.external_id}\""

attribute_mapping = {
"google.subject" = "assertion.arn"
"attribute.aws_account" = "assertion.account"
"attribute.role" = "assertion.arn.extract(\"/assumed-role/{role}/\")"
"attribute.session" = "assertion.arn.extract(\"/assumed-role/{role_and_session}/\").extract(\"/{session}\")"
}

aws {
account_id = data.sysdig_secure_trusted_cloud_identity.trusted_identity.aws_account_id
}
}

resource "google_service_account_iam_member" "controller_binding" {
service_account_id = google_service_account.controller.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.agentless.workload_identity_pool_id}/attribute.aws_role/arn:aws:sts::${data.sysdig_secure_trusted_cloud_identity.trusted_identity.aws_account_id}:assumed-role/${data.sysdig_secure_trusted_cloud_identity.trusted_identity.aws_role_name}/${data.sysdig_secure_tenant_external_id.external_id.external_id}"
}


#--------------------------------------------------------------------------------------------------------------
# Call Sysdig Backend to add the service-principal integration for VM Workload Scanning to the Sysdig Cloud Account
#--------------------------------------------------------------------------------------------------------------
resource "sysdig_secure_cloud_auth_account_component" "google_service_principal" {
account_id = var.sysdig_secure_account_id
type = "COMPONENT_SERVICE_PRINCIPAL"
instance = "secure-vm-workload-scanning"
version = "v0.1.0"
service_principal_metadata = jsonencode({
gcp = {
workload_identity_federation = {
pool_id = google_iam_workload_identity_pool.agentless.workload_identity_pool_id
pool_provider_id = google_iam_workload_identity_pool_provider.agentless.workload_identity_pool_provider_id
project_number = data.google_project.project.number
}
email = google_service_account.controller.email
}
})
depends_on = [
google_service_account.controller,
google_project_iam_custom_role.controller,
google_project_iam_binding.controller_binding,
google_iam_workload_identity_pool.agentless,
google_organization_iam_member.controller,
]
}
35 changes: 35 additions & 0 deletions modules/vm-workload-scanning/organizational.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#--------------#
# Organization #
#--------------#

data "google_organization" "org" {
count = var.is_organizational ? 1 : 0
domain = var.organization_domain
}

###################################################
# Setup Service Account permissions
###################################################

#---------------------------------------------------------------------------------------------
# role permissions for CSPM (GCP Predefined Roles for Sysdig Cloud Secure Posture Management)
#---------------------------------------------------------------------------------------------
resource "google_organization_iam_member" "controller" {
# adding ciem role with permissions to the service account alongside cspm roles
for_each = var.is_organizational ? toset([
"artifactregistry.repositories.downloadArtifacts",
"artifactregistry.repositories.get",
"artifactregistry.repositories.list",
"artifactregistry.dockerimages.get",
"artifactregistry.dockerimages.list",
"storage.objects.get",
"storage.buckets.list",
"storage.objects.list",

# workload identity federation
"iam.serviceAccounts.getAccessToken"]) : []

org_id = data.google_organization.org[0].org_id
role = each.key
member = "serviceAccount:${google_service_account.controller.email}"
}
5 changes: 5 additions & 0 deletions modules/vm-workload-scanning/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
output "vm_workload_scanning_component_id" {
value = "${sysdig_secure_cloud_auth_account_component.google_service_principal.type}/${sysdig_secure_cloud_auth_account_component.google_service_principal.instance}"
description = "Component identifier of service principal created in Sysdig Backend for VM Workload Scanning"
depends_on = [sysdig_secure_cloud_auth_account_component.google_service_principal]
}
28 changes: 28 additions & 0 deletions modules/vm-workload-scanning/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
variable "project_id" {
type = string
description = "GCP Project ID"
}

variable "is_organizational" {
type = bool
description = "Set this field to 'true' to deploy workload scanning to a GCP Organization."
default = false
}

variable "organization_domain" {
type = string
description = "(Optional) Organization domain. e.g. sysdig.com"
default = false
}

# optionals
variable "role_name" {
type = string
description = "Name for the Worker Role on the Customer infrastructure"
default = "SysdigAgentlessWorkloadRole"
}

variable "sysdig_secure_account_id" {
type = string
description = "ID of the Sysdig Cloud Account to enable Config Posture for (in case of organization, ID of the Sysdig management account)"
}
18 changes: 18 additions & 0 deletions modules/vm-workload-scanning/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
terraform {
required_version = ">=1.0"

required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.21.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.1, < 4.0"
}
sysdig = {
source = "sysdiglabs/sysdig"
version = "~> 1.37"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module "vm_workload_scanning" {
source = "../../../modules/vm-workload-scanning"

project_id = module.onboarding.project_id
is_organizational = module.onboarding.is_organizational
organization_domain = module.onboarding.organization_domain
sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}


resource "sysdig_secure_cloud_auth_account_feature" "config_cloud_run" {
account_id = module.onboarding.sysdig_secure_account_id
type = "FEATURE_SECURE_WORKLOAD_SCANNING_CONTAINERS"
enabled = true
components = [module.vm_workload_scanning.vm_workload_scanning_component_id]
depends_on = [module.vm_workload_scanning]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module "vm_workload_scanning" {
source = "../../../modules/vm-workload-scanning"

project_id = module.onboarding.project_id
is_organizational = module.onboarding.is_organizational
organization_domain = module.onboarding.organization_domain
sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}


resource "sysdig_secure_cloud_auth_account_feature" "config_functions" {
account_id = module.onboarding.sysdig_secure_account_id
type = "FEATURE_SECURE_WORKLOAD_SCANNING_FUNCTIONS"
enabled = true
components = [module.vm_workload_scanning.vm_workload_scanning_component_id]
depends_on = [module.vm_workload_scanning]
}
17 changes: 17 additions & 0 deletions test/examples/modular_organization/vm-workload-scanning-gke.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module "vm_workload_scanning" {
source = "../../../modules/vm-workload-scanning"

project_id = module.onboarding.project_id
is_organizational = module.onboarding.is_organizational
organization_domain = module.onboarding.organization_domain
sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}


resource "sysdig_secure_cloud_auth_account_feature" "config_gke" {
account_id = module.onboarding.sysdig_secure_account_id
type = "FEATURE_SECURE_WORKLOAD_SCANNING_KUBERNETES"
enabled = true
components = [module.vm_workload_scanning.vm_workload_scanning_component_id]
depends_on = [module.vm_workload_scanning]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module "vm_workload_scanning" {
source = "../../../modules/vm-workload-scanning"

project_id = module.onboarding.project_id
sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}


resource "sysdig_secure_cloud_auth_account_feature" "config_cloud_run" {
account_id = module.onboarding.sysdig_secure_account_id
type = "FEATURE_SECURE_WORKLOAD_SCANNING_CONTAINERS"
enabled = true
components = [module.vm_workload_scanning.vm_workload_scanning_component_id]
depends_on = [module.vm_workload_scanning]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module "vm_workload_scanning" {
source = "../../../modules/vm-workload-scanning"

project_id = module.onboarding.project_id
sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}


resource "sysdig_secure_cloud_auth_account_feature" "config_functions" {
account_id = module.onboarding.sysdig_secure_account_id
type = "FEATURE_SECURE_WORKLOAD_SCANNING_FUNCTIONS"
enabled = true
components = [module.vm_workload_scanning.vm_workload_scanning_component_id]
depends_on = [module.vm_workload_scanning]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module "vm_workload_scanning" {
source = "../../../modules/vm-workload-scanning"

project_id = module.onboarding.project_id
sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}


resource "sysdig_secure_cloud_auth_account_feature" "config_gke" {
account_id = module.onboarding.sysdig_secure_account_id
type = "FEATURE_SECURE_WORKLOAD_SCANNING_KUBERNETES"
enabled = true
components = [module.vm_workload_scanning.vm_workload_scanning_component_id]
depends_on = [module.vm_workload_scanning]
}
Loading