| 
 | 1 | +#-----------------------------------------------------------------------------------------  | 
 | 2 | +# Fetch the data sources  | 
 | 3 | +#-----------------------------------------------------------------------------------------  | 
 | 4 | +data "sysdig_secure_agentless_scanning_assets" "assets" {}  | 
 | 5 | + | 
 | 6 | +#-----------------------------------------------------------------------------------------  | 
 | 7 | +# These locals indicate the suffix to create unique name for resources and permissions  | 
 | 8 | +#-----------------------------------------------------------------------------------------  | 
 | 9 | +locals {  | 
 | 10 | +  suffix = var.suffix == null ? random_id.suffix[0].hex : var.suffix  | 
 | 11 | +  host_discovery_permissions = [  | 
 | 12 | +    # networks  | 
 | 13 | +    "compute.networks.list",  | 
 | 14 | +    "compute.networks.get",  | 
 | 15 | +    # instances  | 
 | 16 | +    "compute.instances.list",  | 
 | 17 | +    "compute.instances.get",  | 
 | 18 | +    # disks  | 
 | 19 | +    "compute.disks.list",  | 
 | 20 | +    "compute.disks.get",  | 
 | 21 | +    # workload identity federation  | 
 | 22 | +    "iam.serviceAccounts.getAccessToken",  | 
 | 23 | +  ]  | 
 | 24 | +  host_scan_permissions = [  | 
 | 25 | +    # general stuff  | 
 | 26 | +    "compute.zoneOperations.get",  | 
 | 27 | +    # disks  | 
 | 28 | +    "compute.disks.get",  | 
 | 29 | +    "compute.disks.useReadOnly",  | 
 | 30 | +  ]  | 
 | 31 | +}  | 
 | 32 | + | 
 | 33 | +#-----------------------------------------------------------------------------------------------------------------------  | 
 | 34 | +# A random resource is used to generate unique Agentless Scan name suffix for resources.  | 
 | 35 | +# This prevents conflicts when recreating an Agentless Scan resources with the same name.  | 
 | 36 | +#-----------------------------------------------------------------------------------------------------------------------  | 
 | 37 | +resource "random_id" "suffix" {  | 
 | 38 | +  count       = var.suffix == null ? 1 : 0  | 
 | 39 | +  byte_length = 3  | 
 | 40 | +}  | 
 | 41 | + | 
 | 42 | + | 
 | 43 | +resource "google_service_account" "controller" {  | 
 | 44 | +  project      = var.project_id  | 
 | 45 | +  account_id   = "sysdig-ahs-${local.suffix}"  | 
 | 46 | +  display_name = "Sysdig Agentless Host Scanning"  | 
 | 47 | +}  | 
 | 48 | + | 
 | 49 | +#-----------------------------------------------------------------------------------------------------------------------  | 
 | 50 | +# Configure Workload Identity Federation for auth  | 
 | 51 | +# See https://cloud.google.com/iam/docs/access-resources-aws  | 
 | 52 | +#-----------------------------------------------------------------------------------------------------------------------  | 
 | 53 | + | 
 | 54 | +resource "google_iam_workload_identity_pool" "agentless" {  | 
 | 55 | +  workload_identity_pool_id = "sysdig-ahs-${local.suffix}"  | 
 | 56 | +}  | 
 | 57 | + | 
 | 58 | +resource "google_iam_workload_identity_pool_provider" "agentless" {  | 
 | 59 | +  count = data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id != null ? 1 : 0  | 
 | 60 | + | 
 | 61 | +  lifecycle {  | 
 | 62 | +    precondition {  | 
 | 63 | +      condition     = (data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id != null && var.sysdig_account_id == null)  | 
 | 64 | +      error_message = "Cannot provide both sysdig_backend or sysdig_account_id"  | 
 | 65 | +    }  | 
 | 66 | +  }  | 
 | 67 | + | 
 | 68 | +  workload_identity_pool_id          = google_iam_workload_identity_pool.agentless.workload_identity_pool_id  | 
 | 69 | +  workload_identity_pool_provider_id = "sysdig-ahs-${local.suffix}"  | 
 | 70 | +  display_name                       = "Sysdig Agentless Controller"  | 
 | 71 | +  description                        = "AWS identity pool provider for Sysdig Secure Agentless Host Scanning"  | 
 | 72 | +  disabled                           = false  | 
 | 73 | + | 
 | 74 | +  attribute_condition = "attribute.aws_account==\"${data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id}\""  | 
 | 75 | + | 
 | 76 | +  attribute_mapping = {  | 
 | 77 | +    "google.subject"        = "assertion.arn"  | 
 | 78 | +    "attribute.aws_account" = "assertion.account"  | 
 | 79 | +    "attribute.role"        = "assertion.arn.extract(\"/assumed-role/{role}/\")"  | 
 | 80 | +    "attribute.session"     = "assertion.arn.extract(\"/assumed-role/{role_and_session}/\").extract(\"/{session}\")"  | 
 | 81 | +  }  | 
 | 82 | + | 
 | 83 | +  aws {  | 
 | 84 | +    account_id = data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id  | 
 | 85 | +  }  | 
 | 86 | +}  | 
 | 87 | + | 
 | 88 | +resource "google_service_account_iam_member" "controller_custom" {  | 
 | 89 | +  count = data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id != null ? 1 : 0  | 
 | 90 | + | 
 | 91 | +  lifecycle {  | 
 | 92 | +    precondition {  | 
 | 93 | +      condition     = (data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id != null && var.sysdig_account_id == null)  | 
 | 94 | +      error_message = "Cannot provide both sysdig_backend or sysdig_account_id"  | 
 | 95 | +    }  | 
 | 96 | +  }  | 
 | 97 | + | 
 | 98 | +  service_account_id = google_service_account.controller.name  | 
 | 99 | +  role               = "roles/iam.workloadIdentityUser"  | 
 | 100 | +  member             = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.agentless.name}/attribute.aws_account/${data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id}"  | 
 | 101 | +}  | 
 | 102 | + | 
 | 103 | +resource "google_iam_workload_identity_pool_provider" "agentless_gcp" {  | 
 | 104 | +  count = var.sysdig_account_id != null ? 1 : 0  | 
 | 105 | + | 
 | 106 | +  lifecycle {  | 
 | 107 | +    precondition {  | 
 | 108 | +      condition     = (data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id == null && var.sysdig_account_id != null)  | 
 | 109 | +      error_message = "Cannot provide both sysdig_backend or sysdig_account_id"  | 
 | 110 | +    }  | 
 | 111 | +  }  | 
 | 112 | + | 
 | 113 | +  workload_identity_pool_id          = google_iam_workload_identity_pool.agentless.workload_identity_pool_id  | 
 | 114 | +  workload_identity_pool_provider_id = "sysdig-ahs-${local.suffix}-gcp"  | 
 | 115 | +  display_name                       = "Sysdig Agentless Controller"  | 
 | 116 | +  description                        = "GCP identity pool provider for Sysdig Secure Agentless Host Scanning"  | 
 | 117 | +  disabled                           = false  | 
 | 118 | + | 
 | 119 | +  attribute_condition = "google.subject == \"${var.sysdig_account_id}\""  | 
 | 120 | + | 
 | 121 | +  attribute_mapping = {  | 
 | 122 | +    "google.subject"  = "assertion.sub"  | 
 | 123 | +    "attribute.sa_id" = "assertion.sub"  | 
 | 124 | +  }  | 
 | 125 | + | 
 | 126 | +  oidc {  | 
 | 127 | +    issuer_uri = "https://accounts.google.com"  | 
 | 128 | +  }  | 
 | 129 | +}  | 
 | 130 | + | 
 | 131 | +resource "google_service_account_iam_member" "controller_custom_gcp" {  | 
 | 132 | +  count = var.sysdig_account_id != null ? 1 : 0  | 
 | 133 | + | 
 | 134 | +  lifecycle {  | 
 | 135 | +    precondition {  | 
 | 136 | +      condition     = (data.sysdig_secure_agentless_scanning_assets.assets.backend.cloud_id == null && var.sysdig_account_id != null)  | 
 | 137 | +      error_message = "Cannot provide both sysdig_backend or sysdig_account_id"  | 
 | 138 | +    }  | 
 | 139 | +  }  | 
 | 140 | + | 
 | 141 | +  service_account_id = google_service_account.controller.name  | 
 | 142 | +  role               = "roles/iam.workloadIdentityUser"  | 
 | 143 | +  member             = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.agentless.name}/attribute.sa_id/${var.sysdig_account_id}"  | 
 | 144 | +}  | 
 | 145 | + | 
 | 146 | +#-----------------------------------------------------------------------------------------  | 
 | 147 | +# Custom IAM roles and bindings  | 
 | 148 | +#-----------------------------------------------------------------------------------------  | 
 | 149 | + | 
 | 150 | +resource "google_project_iam_custom_role" "controller" {  | 
 | 151 | +  count = var.is_organizational ? 0 : 1  | 
 | 152 | + | 
 | 153 | +  project     = var.project_id  | 
 | 154 | +  role_id     = "${var.role_name}Discovery${local.suffix}"  | 
 | 155 | +  title       = "${var.role_name}, for Host Discovery"  | 
 | 156 | +  permissions = local.host_discovery_permissions  | 
 | 157 | +}  | 
 | 158 | + | 
 | 159 | +resource "google_project_iam_binding" "controller_custom" {  | 
 | 160 | +  count = var.is_organizational ? 0 : 1  | 
 | 161 | + | 
 | 162 | +  project = var.project_id  | 
 | 163 | +  role    = google_project_iam_custom_role.controller[0].id  | 
 | 164 | +  members = [  | 
 | 165 | +    "serviceAccount:${google_service_account.controller.email}",  | 
 | 166 | +  ]  | 
 | 167 | +}  | 
 | 168 | + | 
 | 169 | +resource "google_project_iam_custom_role" "worker_role" {  | 
 | 170 | +  count = var.is_organizational ? 0 : 1  | 
 | 171 | + | 
 | 172 | +  project     = var.project_id  | 
 | 173 | +  role_id     = "${var.role_name}Scan${local.suffix}"  | 
 | 174 | +  title       = "${var.role_name}, for Host Scan"  | 
 | 175 | +  permissions = local.host_scan_permissions  | 
 | 176 | +}  | 
 | 177 | + | 
 | 178 | +resource "google_project_iam_binding" "admin_account_iam" {  | 
 | 179 | +  count = var.is_organizational ? 0 : 1  | 
 | 180 | + | 
 | 181 | +  project = var.project_id  | 
 | 182 | +  role    = google_project_iam_custom_role.worker_role[0].id  | 
 | 183 | +  members = [  | 
 | 184 | +    "serviceAccount:${data.sysdig_secure_agentless_scanning_assets.assets.gcp.worker_identity}",  | 
 | 185 | +  ]  | 
 | 186 | +}  | 
 | 187 | + | 
 | 188 | +#-----------------------------------------------------------------------------------------------------------------------------------------  | 
 | 189 | +# Call Sysdig Backend to add the agentless-scan integration to the Sysdig Cloud Account  | 
 | 190 | +#  | 
 | 191 | +# Note (optional): To ensure this gets called after all cloud resources are created, add  | 
 | 192 | +# explicit dependency using depends_on  | 
 | 193 | +#-----------------------------------------------------------------------------------------------------------------------------------------  | 
 | 194 | + | 
 | 195 | +resource "sysdig_secure_cloud_auth_account_component" "gcp_agentless_scan" {  | 
 | 196 | +  account_id = var.sysdig_secure_account_id  | 
 | 197 | +  type       = "COMPONENT_SERVICE_PRINCIPAL"  | 
 | 198 | +  instance   = "secure-scanning"  | 
 | 199 | +  version    = "v0.1.0"  | 
 | 200 | +  service_principal_metadata = jsonencode({  | 
 | 201 | +    gcp = {  | 
 | 202 | +      workload_identity_federation = {  | 
 | 203 | +        pool_provider_id = data.sysdig_secure_agentless_scanning_assets.assets.gcp.worker_identity != null ? google_iam_workload_identity_pool_provider.agentless[0].name : var.sysdig_account_id != null ? google_iam_workload_identity_pool_provider.agentless_gcp[0].name : null  | 
 | 204 | +      }  | 
 | 205 | +      email = google_service_account.controller.email  | 
 | 206 | +    }  | 
 | 207 | +  })  | 
 | 208 | +}  | 
0 commit comments