Skip to content

Commit

Permalink
feat(vm,cloud-scan): enables organizational use-case (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
iru authored Mar 18, 2024
1 parent 3ee5fc4 commit 66e6f78
Show file tree
Hide file tree
Showing 20 changed files with 241 additions and 64 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci-pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
- "secure_config_posture_identity_access/organization/main.tf"
- "secure_threat_detection/single/main.tf"
- "secure_threat_detection/organization/main.tf"
- "agentless-scan/organization/main.tf"
steps:
- name: Set up Go
uses: actions/setup-go@v2
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ deps: $(TFLINT)
lint: $(TFLINT)
$(MAKE) -C modules lint

fmt-check: fmt
fmt:
terraform fmt -check -recursive modules
fmt-fix:
terraform fmt -recursive modules

clean:
find -name ".terraform" -type d | xargs rm -rf
Expand Down
30 changes: 22 additions & 8 deletions modules/services/agentless-scan/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@ The following resources will be created on each instrumented project:
- For the **Host Data Extraction**: Enable Sysdig to create a disk copy on our SaaS platform, to be able to extract
the data required for security assessment.

![permission-diagram.png](permission-diagram.png)

Organizational support will be added later on.
## Single Project Setup
![permission_diagram_single](./permissions_diagram_single.png)

## Organizational Setup

Set `is_organizatinal=true` together with the `organization_domain=YOUR_DOMAIN`

![permission_diagram_org](./permissions_diagram_org.png)


<br/><br/>

Expand All @@ -37,8 +44,8 @@ While on Controlled Availability check with your Sysdig representative.

| Name | Version |
|------|---------|
| <a name="provider_google"></a> [google](#provider\_google) | >= 4.1, < 5.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 3.1, < 4.0 |
| <a name="provider_google"></a> [google](#provider\_google) | 4.84.0 |
| <a name="provider_random"></a> [random](#provider\_random) | 3.6.0 |

## Modules

Expand All @@ -51,26 +58,33 @@ No modules.
| [google_iam_workload_identity_pool.agentless](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool) | resource |
| [google_iam_workload_identity_pool_provider.agentless](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource |
| [google_iam_workload_identity_pool_provider.agentless_gcp](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource |
| [google_project_iam_binding.admin-account-iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_binding) | resource |
| [google_organization_iam_binding.admin_account_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/organization_iam_binding) | resource |
| [google_organization_iam_binding.controller_custom](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/organization_iam_binding) | resource |
| [google_organization_iam_custom_role.controller](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/organization_iam_custom_role) | resource |
| [google_organization_iam_custom_role.worker_role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/organization_iam_custom_role) | resource |
| [google_project_iam_binding.admin_account_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_binding) | resource |
| [google_project_iam_binding.controller_custom](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_binding) | resource |
| [google_project_iam_custom_role.controller](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_custom_role) | resource |
| [google_project_iam_custom_role.worker_role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_custom_role) | resource |
| [google_service_account.controller](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account) | resource |
| [google_service_account_iam_member.controller_custom](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |
| [google_service_account_iam_member.controller_custom_gcp](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |
| [random_id.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
| [google_organization.org](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/organization) | data source |
| [google_project.project](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/project) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_is_organizational"></a> [is\_organizational](#input\_is\_organizational) | Optional. Determines whether module must scope whole organization. Otherwise single project will be scoped | `bool` | `false` | no |
| <a name="input_organization_domain"></a> [organization\_domain](#input\_organization\_domain) | Optional. If `is_organizational=true` is set, its mandatory to specify this value, with the GCP Organization domain. e.g. sysdig.com | `string` | `null` | no |
| <a name="input_project_id"></a> [project\_id](#input\_project\_id) | GCP Project ID | `string` | n/a | yes |
| <a name="input_worker_identity"></a> [worker\_identity](#input\_worker\_identity) | Sysdig provided Identity for the Service Account in charge of performing the host disk analysis | `string` | n/a | yes |
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | Name for the Worker Role on the Customer infrastructure | `string` | `"SysdigAgentlessHostRole"` | no |
| <a name="input_suffix"></a> [suffix](#input\_suffix) | By default a random value will be autogenerated.<br/>Suffix word to enable multiple deployments with different naming<br/>(Workload Identity Pool and Providers have a soft deletion on Google Platform that will disallow name re-utilization) | `string` | `null` | no |
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | Optional. Name for the Worker Role on the Customer infrastructure | `string` | `"SysdigAgentlessHostRole"` | no |
| <a name="input_suffix"></a> [suffix](#input\_suffix) | Optional. Suffix word to enable multiple deployments with different naming<br/>(Workload Identity Pool and Providers have a soft deletion on Google Platform that will disallow name re-utilization)<br/>By default a random value will be autogenerated. | `string` | `null` | no |
| <a name="input_sysdig_account_id"></a> [sysdig\_account\_id](#input\_sysdig\_account\_id) | Sysdig provided GCP Account designated for the host scan.<br/>One of `sysdig_backend` or `sysdig_account_id`must be provided | `string` | `null` | no |
| <a name="input_sysdig_backend"></a> [sysdig\_backend](#input\_sysdig\_backend) | Sysdig provided AWS Account designated for the host scan.<br/>One of `sysdig_backend` or `sysdig_account_id`must be provided | `string` | `null` | no |
| <a name="input_worker_identity"></a> [worker\_identity](#input\_worker\_identity) | Sysdig provided Identity for the Service Account in charge of performing the host disk analysis | `string` | n/a | yes |

## Outputs

Expand Down
28 changes: 0 additions & 28 deletions modules/services/agentless-scan/controller.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,6 @@ resource "google_service_account" "controller" {
display_name = "Sysdig Agentless Host Scanning"
}

resource "google_project_iam_custom_role" "controller" {
project = var.project_id
role_id = "${var.role_name}Controller${title(local.suffix)}"
title = "Role for Sysdig Agentless Host Workers"
permissions = [
# networks
"compute.networks.list",
"compute.networks.get",
# instances
"compute.instances.list",
"compute.instances.get",
# disks
"compute.disks.list",
"compute.disks.get",
# workload identity federation
"iam.serviceAccounts.getAccessToken",
]
}

resource "google_project_iam_binding" "controller_custom" {
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-ahs-${local.suffix}"
}
Expand Down
18 changes: 18 additions & 0 deletions modules/services/agentless-scan/controller_org.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "google_organization_iam_custom_role" "controller" {
count = local.is_organizational ? 1 : 0

org_id = data.google_organization.org[0].org_id
role_id = "${var.role_name}Discovery${title(local.suffix)}"
title = "${var.role_name}, for Host Discovery"
permissions = local.host_discovery_permissions
}

resource "google_organization_iam_binding" "controller_custom" {
count = local.is_organizational ? 1 : 0

org_id = data.google_organization.org[0].org_id
role = google_organization_iam_custom_role.controller[0].id
members = [
"serviceAccount:${google_service_account.controller.email}",
]
}
18 changes: 18 additions & 0 deletions modules/services/agentless-scan/controller_single.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "google_project_iam_custom_role" "controller" {
count = local.is_organizational ? 0 : 1

project = var.project_id
role_id = "${var.role_name}Discovery${title(local.suffix)}"
title = "${var.role_name}, for Host Discovery"
permissions = local.host_discovery_permissions
}

resource "google_project_iam_binding" "controller_custom" {
count = local.is_organizational ? 0 : 1

project = var.project_id
role = google_project_iam_custom_role.controller[0].id
members = [
"serviceAccount:${google_service_account.controller.email}",
]
}
5 changes: 5 additions & 0 deletions modules/services/agentless-scan/data.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
data "google_project" "project" {
project_id = var.project_id
}

data "google_organization" "org" {
count = local.is_organizational ? 1 : 0
domain = var.organization_domain
}
24 changes: 24 additions & 0 deletions modules/services/agentless-scan/locals.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
locals {
suffix = var.suffix == null ? random_id.suffix[0].hex : var.suffix

is_organizational = var.is_organizational && var.organization_domain != null ? true : false

host_discovery_permissions = [
# networks
"compute.networks.list",
"compute.networks.get",
# instances
"compute.instances.list",
"compute.instances.get",
# disks
"compute.disks.list",
"compute.disks.get",
# workload identity federation
"iam.serviceAccounts.getAccessToken",
]

host_scan_permissions = [
# general stuff
"compute.zoneOperations.get",
# disks
"compute.disks.get",
"compute.disks.useReadOnly",
]
}


Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 18 additions & 7 deletions modules/services/agentless-scan/variables.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# mandatory
variable "project_id" {
type = string
description = "GCP Project ID"
Expand All @@ -20,18 +21,28 @@ variable "sysdig_account_id" {
default = null
}


# optionals
# optional
variable "role_name" {
type = string
description = "Name for the Worker Role on the Customer infrastructure"
default = "SysdigAgentlessHostRole"
description = "Optional. Name for Sysdig operations on discovery and scan"
default = "SysdigCloudVM"
}



variable "suffix" {
type = string
description = "By default a random value will be autogenerated.<br/>Suffix word to enable multiple deployments with different naming<br/>(Workload Identity Pool and Providers have a soft deletion on Google Platform that will disallow name re-utilization)"
description = "Optional. Suffix word to enable multiple deployments with different naming<br/>(Workload Identity Pool and Providers have a soft deletion on Google Platform that will disallow name re-utilization)<br/>By default a random value will be autogenerated."
default = null
}
}

variable "is_organizational" {
description = "Optional. Determines whether module must scope whole organization. Otherwise single project will be scoped"
type = bool
default = false
}

variable "organization_domain" {
type = string
description = "Optional. If `is_organizational=true` is set, its mandatory to specify this value, with the GCP Organization domain. e.g. sysdig.com"
default = null
}
21 changes: 0 additions & 21 deletions modules/services/agentless-scan/worker.tf

This file was deleted.

18 changes: 18 additions & 0 deletions modules/services/agentless-scan/worker_org.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "google_organization_iam_custom_role" "worker_role" {
count = local.is_organizational ? 1 : 0

org_id = data.google_organization.org[0].org_id
role_id = "${var.role_name}Scan${title(local.suffix)}"
title = "${var.role_name}, for Host Scan"
permissions = local.host_scan_permissions
}

resource "google_organization_iam_binding" "admin_account_iam" {
count = local.is_organizational ? 1 : 0

org_id = data.google_organization.org[0].org_id
role = google_organization_iam_custom_role.worker_role[0].id
members = [
"serviceAccount:${var.worker_identity}",
]
}
18 changes: 18 additions & 0 deletions modules/services/agentless-scan/worker_single.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "google_project_iam_custom_role" "worker_role" {
count = local.is_organizational ? 0 : 1

project = var.project_id
role_id = "${var.role_name}Scan${title(local.suffix)}"
title = "${var.role_name}, for Host Scan"
permissions = local.host_scan_permissions
}

resource "google_project_iam_binding" "admin_account_iam" {
count = local.is_organizational ? 0 : 1

project = var.project_id
role = google_project_iam_custom_role.worker_role[0].id
members = [
"serviceAccount:${var.worker_identity}",
]
}
6 changes: 6 additions & 0 deletions test/examples/agentless-scan/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

note;

- we test the cloud-scan module together with its dependencies on the minimal use-case
- cspm; for discovery + organizational setup (`secure-onboarding` component)
- sysdig provider `sysdig_secure_cloud_auth_account`; for authentication
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# this is required for organizational setup (+cloud-host vm)

module "organization-posture" {
source = "sysdiglabs/secure/google//modules/services/service-principal"
project_id = "org-child-project-1"
service_account_name = "sysdig-secure-igm6"
is_organizational = true
organization_domain = "draios.com"
}
14 changes: 14 additions & 0 deletions test/examples/agentless-scan/organization/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
provider "google"{
project="mytestproject"
}


module "cloud_host" {
source = "../../../..//modules/services/agentless-scan"
project_id = "mytestproject"
sysdig_account_id = "012345678"
worker_identity = "[email protected]"

is_organizational = true
organization_domain = "myorg.com"
}
18 changes: 18 additions & 0 deletions test/examples/agentless-scan/organization/provider.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.1, < 5.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.1, < 4.0"
}
sysdig = {
source = "sysdiglabs/sysdig"
version = ">= 1.23.1"
}
}
}
Loading

0 comments on commit 66e6f78

Please sign in to comment.