diff --git a/modules/integrations/pub-sub/README.md b/modules/integrations/pub-sub/README.md new file mode 100644 index 0000000..27d53a6 --- /dev/null +++ b/modules/integrations/pub-sub/README.md @@ -0,0 +1,108 @@ +# GCP PubSub Module + +This Module creates the resources required to send AuditLogs logs to Sysdig via GCP Pub Subscription. These resources enable Threat Detection in the given GCP project or organization. +Before applying the changes defined in this module, the following operations need to be performed on the target GCP environment: + +- The APIs needed for the CDR/CIEM feature are listed below: + - Cloud Pub/Sub API + +- The following resources will be created in each instrumented project: + - A `PubSub Topic` to send the AuditLogs from the project + - A `Logging Sink` that export AuditLogs to the PubSub topic + - A `PubSub Topic IAM member` to assign a role to the PubSub topic + - A `PubSub Subscription` to allows receiving messages from the PubSub topic, including its `Service Account` + - An `IAM Workload Identity Pool` that enables identities from external systems(AWS) tp access GCP resources through IAM + - An `IAM role and member` that provides the required permissions for Sysdig Backend to read cloud resources created for data ingestion + +When run in organizational mode, this module is similar however the main difference is that an organizational sink is used +instead of a project-specific one, as well as enabling AuditLogs for all the projects that fall within the organization. + +This module will also deploy a Webhook Datasource Component in Sysdig Backend for onboarded Sysdig Cloud Account. + + +## Requirements + +| Name | Version | +|---------------------------------------------------------------------------|-----------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [google](#requirement\_google) | >= 4.21.0 | +| [sysdig](#requirement\_sysdig) | | + +## Providers + +| Name | Version | +|------------------------------------------------------------------|-----------| +| [google](#provider\_google) | >= 4.21.0 | +| [random](#requirement\_random) | >= 3.1 | +| [sysdig](#requirement\_sysdig) | | + + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------| +| [random_id.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [google_project_iam_audit_config.audit_config](https://registry.terraform.io/providers/hashicorp/google/3.0.0-beta.1/docs/resources/google_project_iam#google_project_iam_audit_config) | resource | +| [google_pubsub_topic.ingestion_topic](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_topic.html) | resource | +| [google_pubsub_topic.deadletter_topic](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_topic.html) | resource | +| [google_logging_project_sink.ingestion_sink](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/logging_project_sink) | resource | +| [google_pubsub_topic_iam_member.publisher_iam_member](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_topic_iam#google_pubsub_topic_iam_member) | resource | +| [google_service_account.push_auth](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account) | resource | +| [google_service_account_iam_binding.push_auth_binding](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam#google_service_account_iam_binding) | resource | +| [google_pubsub_subscription.ingestion_topic_push_subscription](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_subscription.html) | resource | +| [google_iam_workload_identity_pool.ingestion_auth_pool](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool) | resource | +| [google_iam_workload_identity_pool_provider.ingestion_auth_pool_provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource | +| [google_project_iam_custom_role.custom_ingestion_auth_role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam_custom_role) | resource | +| [google_project_iam_member.custom](https://registry.terraform.io/providers/hashicorp/google/3.22.0/docs/resources/google_project_iam#google_project_iam_member) | resource | +| [google_project_iam_member.identity_mgmt](https://registry.terraform.io/providers/hashicorp/google/3.22.0/docs/resources/google_project_iam#google_project_iam_member) | resource | +| [google_service_account_iam_member.custom_auth](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam#google_service_account_iam_member) | resource | +| [sysdig_secure_trusted_cloud_identity.trusted_identity](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/data-sources/secure_trusted_cloud_identity) | data source | +| [sysdig_secure_cloud_auth_account_component.gcp_pubsub_datasource](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/resources/secure_cloud_auth_account_component) | resource | +| [sysdig_secure_tenant_external_id](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/data-sources/secure_tenant_external_id) | data source | +| [sysdig_secure_cloud_ingestion_assets](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/data-sources/secure_cloud_ingestion_assets) | data source | +| [google_project.project](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/project) | data source | +| [google_organization.org](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/organization) | data source | +| [google_organization_iam_audit_config.audit_config](https://registry.terraform.io/providers/hashicorp/google/3.24.0/docs/resources/google_organization_iam_audit_config) | resource | +| [google_logging_organization_sink.ingestion_sink](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/logging_organization_sink) | resoruce | +| [google_organization_iam_custom_role.custom_ingestion_auth_role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_organization_iam_custom_role) | resource | +| [google_organization_iam_member.custom](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_organization_iam#google_organization_iam_member) | resource | +| [google_organization_iam_member.identity_mgmt](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_organization_iam#google_organization_iam_member) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------:| +| [ack\_deadline\_seconds](#input\_ack\_deadline\_seconds) | (Optional) Maximum time in seconds after Sysdig's subscriber receives a message before the subscriber should acknowledge the message | `number` | `60` | no | +| [is\_organizational](#input\_is\_organizational) | (Optional) Set this field to 'true' to deploy secure-for-cloud to a GCP Organization. | `bool` | `false` | no | +| [labels](#input\_labels) | (Optional) Labels to be associated with Sysdig-originated resources | `map(string)` |
{
"originator": "sysdig"
}
| no | +| [max\_delivery\_attempts](#input\_max\_delivery\_attempts) | (Optional) Number of attempts redelivering missed messages from the deadletter topic to the main one | `number` | `5` | no | +| [maximum\_backoff](#input\_maximum\_backoff) | (Optional) Maximum backoff time for exponential backoff of the push subscription retry policy | `string` | `"600s"` | no | +| [message\_retention\_duration](#input\_message\_retention\_duration) | (Optional) How long unacknowledged messages are retained in Sysdig's subscription backlog, from the moment a message is published | `string` | `"604800s"` | no | +| [minimum\_backoff](#input\_minimum\_backoff) | (Optional) Minimum backoff time for exponential backoff of the push subscription retry policy | `string` | `"10s"` | no | +| [organization\_domain](#input\_organization\_domain) | Organization domain. e.g. sysdig.com | `string` | `""` | no | +| [project\_id](#input\_project\_id) | (Required) Target Project identifier provided by the customer | `string` | n/a | yes | +| [suffix](#input\_suffix) | (Optional) Suffix to uniquely identify resources during multiple installs. If not provided, random value is autogenerated | `string` | `null` | no | +| [audit\_log\_config](#input\_audit\_log\_config) | List of services and their audit log configurations to be ingested. Default is to ingest all logs. |
list(object({
service = string,
log_config = list(object({
log_type = string,
exempted_members = optional(list(string))
}))
}))
|
[
{
"log_config": [
{
"log_type": "ADMIN_READ"
},
{
"log_type": "DATA_READ"
},
{
"log_type": "DATA_WRITE"
}
],
"service": "allServices"
}
]
| no | +| [ingestion\_sink\_filter](#input\_ingestion\_sink\_filter) | Filter the Sink is set up with. Ingests AuditLogs by default. | `string` | `protoPayload.@type = "type.googleapis.com/google.cloud.audit.AuditLog"` | no | +| [exclude\_logs\_filter](#input\_exclude\_logs\_filter) | Filter to exclude logs from ingestion. Default is to ingest all google.cloud.audit.AuditLog logs. with no exclusions. |
list(object({
name = string,
description = optional(string),
filter = string,
disabled = optional(bool)
}))
| `[]` | no | +| [sysdig\_secure\_account\_id](#input\_sysdig\_secure\_account\_id) | ID of the Sysdig Cloud Account to enable Event Bridge integration for (incase of organization, ID of the Sysdig management account) | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| +| [pubsub\_datasource\_component\_id](#pubsub\_datasource\_component\_id) | Component identifier of Pub Sub integration created in Sysdig Backend for Log Ingestion | + + + +## Authors + +Module is maintained by [Sysdig](https://sysdig.com). + +## License + +Apache 2 Licensed. See LICENSE for full details. diff --git a/modules/integrations/pub-sub/main.tf b/modules/integrations/pub-sub/main.tf new file mode 100644 index 0000000..afe2c9e --- /dev/null +++ b/modules/integrations/pub-sub/main.tf @@ -0,0 +1,274 @@ +#----------------------------------------------------------------------------------------------------------------------------------------- +# For Organizational installs, see organizational.tf. +# This module takes care of provisioning the necessary resources to make Sysdig's backend able to ingest data from a +# single GCP project. +# +# Note: The alternative definitions for the organizational variant of this module are contained +# in organizational.tf. The only differences w.r.t. the standalone template is in using an +# organizational sink instead of a project-specific one, as well as enabling AuditLogs for +# all the projects that fall within the organization. +#----------------------------------------------------------------------------------------------------------------------------------------- + +#----------------------------------------------------------------------------------------- +# Fetch the data sources +#----------------------------------------------------------------------------------------- +data "sysdig_secure_trusted_cloud_identity" "trusted_identity" { + cloud_provider = "gcp" +} + +data "google_project" "project" { + project_id = var.project_id +} + +data "sysdig_secure_tenant_external_id" "external_id" {} + +data "sysdig_secure_cloud_ingestion_assets" "assets" {} + +#----------------------------------------------------------------------------------------- +# These locals indicate the suffix to create unique name for resources +#----------------------------------------------------------------------------------------- +locals { + suffix = var.suffix == null ? random_id.suffix[0].hex : var.suffix + role_name = "SysdigIngestionAuthRole" +} + + +#----------------------------------------------------------------------------------------------------------------------- +# A random resource is used to generate unique Pub Sub name suffix for resources. +# This prevents conflicts when recreating a Pub Sub resources with the same name. +#----------------------------------------------------------------------------------------------------------------------- +resource "random_id" "suffix" { + count = var.suffix == null ? 1 : 0 + byte_length = 3 +} + +#----------------------------------------------------------------------------------------- +# Audit Logs +#----------------------------------------------------------------------------------------- +locals { + # Data structure will be a map for each service, that can have multiple audit_log_config + audit_log_config = { for audit in var.audit_log_config : + audit["service"] => { + log_config = audit["log_config"] + } + } +} + +resource "google_project_iam_audit_config" "audit_config" { + for_each = var.is_organizational ? {} : local.audit_log_config + project = var.project_id + service = each.key + + dynamic "audit_log_config" { + for_each = each.value.log_config + iterator = log_config + content { + log_type = log_config.value.log_type + exempted_members = log_config.value.exempted_members + } + } +} + +#----------------------------------------------------------------------------------------- +# Ingestion Topic +#----------------------------------------------------------------------------------------- +resource "google_pubsub_topic" "ingestion_topic" { + name = "ingestion_topic" + labels = var.labels + project = var.project_id + message_retention_duration = var.message_retention_duration +} + +resource "google_pubsub_topic" "deadletter_topic" { + name = "dl-${google_pubsub_topic.ingestion_topic.name}" + project = var.project_id + message_retention_duration = var.message_retention_duration +} + +#----------------------------------------------------------------------------------------- +# Sink +#----------------------------------------------------------------------------------------- +resource "google_logging_project_sink" "ingestion_sink" { + count = var.is_organizational ? 0 : 1 + name = "${google_pubsub_topic.ingestion_topic.name}_sink" + description = "Sysdig sink to direct the AuditLogs to the PubSub topic used for data gathering" + + # NOTE: The target destination is a PubSub topic + destination = "pubsub.googleapis.com/projects/${var.project_id}/topics/${google_pubsub_topic.ingestion_topic.name}" + filter = var.ingestion_sink_filter + + # Dynamic block to exclude logs from ingestion + dynamic "exclusions" { + for_each = var.exclude_logs_filter + content { + name = exclusions.value.name + description = exclusions.value.description + filter = exclusions.value.filter + disabled = exclusions.value.disabled + } + } + + # NOTE: Used to create a dedicated writer identity and not using the default one + unique_writer_identity = true +} + +resource "google_pubsub_topic_iam_member" "publisher_iam_member" { + project = google_pubsub_topic.ingestion_topic.project + topic = google_pubsub_topic.ingestion_topic.name + role = "roles/pubsub.publisher" + member = var.is_organizational ? google_logging_organization_sink.ingestion_sink[0].writer_identity : google_logging_project_sink.ingestion_sink[0].writer_identity +} + +#----------------------------------------------------------------------------------------- +# Push Subscription +#----------------------------------------------------------------------------------------- +resource "google_service_account" "push_auth" { + account_id = "sysdig-ingestion-${local.suffix}" + display_name = "Sysdig Ingestion Push Auth Service Account" + project = var.project_id +} + +resource "google_service_account_iam_binding" "push_auth_binding" { + service_account_id = google_service_account.push_auth.name + role = "roles/iam.workloadIdentityUser" + + members = [ + "serviceAccount:${google_service_account.push_auth.email}", + ] +} + +resource "google_pubsub_subscription" "ingestion_topic_push_subscription" { + name = "${google_pubsub_topic.ingestion_topic.name}_push_subscription" + topic = google_pubsub_topic.ingestion_topic.name + labels = var.labels + ack_deadline_seconds = var.ack_deadline_seconds + message_retention_duration = var.message_retention_duration + project = var.project_id + + push_config { + push_endpoint = data.sysdig_secure_cloud_ingestion_assets.assets.gcp_metadata.ingestionURL + attributes = { + x-goog-version = "v1" + } + oidc_token { + service_account_email = google_service_account.push_auth.email + audience = "sysdig_secure" + } + } + + retry_policy { + minimum_backoff = var.minimum_backoff + maximum_backoff = var.maximum_backoff + } + + dead_letter_policy { + dead_letter_topic = google_pubsub_topic.deadletter_topic.id + max_delivery_attempts = var.max_delivery_attempts + } +} + +#----------------------------------------------------------------------------------------- +# Configure Workload Identity Federation for auth +# See https://cloud.google.com/iam/docs/access-resources-aws +# ----------------------------------------------------------------------------------------- + +resource "google_iam_workload_identity_pool" "ingestion_auth_pool" { + project = var.project_id + workload_identity_pool_id = "sysdig-ingestion-${local.suffix}" +} + +resource "google_iam_workload_identity_pool_provider" "ingestion_auth_pool_provider" { + project = var.project_id + workload_identity_pool_id = google_iam_workload_identity_pool.ingestion_auth_pool.workload_identity_pool_id + workload_identity_pool_provider_id = "sysdig-ingestion-${local.suffix}" + display_name = "Sysdigcloud ingestion auth" + description = "AWS identity pool provider for Sysdig Secure Data Ingestion resources" + 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_role" = "assertion.arn" + } + + aws { + account_id = data.sysdig_secure_trusted_cloud_identity.trusted_identity.aws_account_id + } +} + +# creating custom role with project-level permissions to access data ingestion resources +resource "google_project_iam_custom_role" "custom_ingestion_auth_role" { + count = var.is_organizational ? 0 : 1 + + project = var.project_id + role_id = "${local.role_name}${local.suffix}" + title = "Sysdigcloud Ingestion Auth Role" + description = "A Role providing the required permissions for Sysdig Backend to read cloud resources created for data ingestion" + permissions = [ + "pubsub.topics.get", + "pubsub.topics.list", + "pubsub.subscriptions.get", + "pubsub.subscriptions.list", + "logging.sinks.get", + "logging.sinks.list", + ] +} + +# adding custom role with project-level permissions to the service account for auth +resource "google_project_iam_member" "custom" { + count = var.is_organizational ? 0 : 1 + + project = var.project_id + role = google_project_iam_custom_role.custom_ingestion_auth_role[0].id + member = "serviceAccount:${google_service_account.push_auth.email}" +} + +# attaching WIF as a member to the service account for auth +resource "google_service_account_iam_member" "custom_auth" { + service_account_id = google_service_account.push_auth.name + role = "roles/iam.workloadIdentityUser" + member = "principalSet://iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.ingestion_auth_pool.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}" +} + +# adding ciem role with permissions to the service account +resource "google_project_iam_member" "identity_mgmt" { + for_each = var.is_organizational ? [] : toset(["roles/recommender.viewer", "roles/iam.serviceAccountViewer", "roles/iam.roleViewer", "roles/container.clusterViewer", "roles/compute.viewer"]) + + project = var.project_id + role = each.key + member = "serviceAccount:${google_service_account.push_auth.email}" +} + +#----------------------------------------------------------------------------------------------------------------------------------------- +# Call Sysdig Backend to add the pub-sub integration to the Sysdig Cloud Account +# +# Note (optional): To ensure this gets called after all cloud resources are created, add +# explicit dependency using depends_on +#----------------------------------------------------------------------------------------------------------------------------------------- + +resource "sysdig_secure_cloud_auth_account_component" "gcp_pubsub_datasource" { + account_id = var.sysdig_secure_account_id + type = "COMPONENT_WEBHOOK_DATASOURCE" + instance = "secure-runtime" + version = "v0.1.0" + webhook_datasource_metadata = jsonencode({ + gcp = { + webhook_datasource = { + pubsub_topic_name = google_pubsub_topic.ingestion_topic.name + sink_name = var.is_organizational ? google_logging_organization_sink.ingestion_sink[0].name : google_logging_project_sink.ingestion_sink[0].name + push_subscription_name = google_pubsub_subscription.ingestion_topic_push_subscription.name + push_endpoint = google_pubsub_subscription.ingestion_topic_push_subscription.push_config[0].push_endpoint + routing_key = data.sysdig_secure_cloud_ingestion_assets.assets.gcp_routing_key + } + service_principal = { + workload_identity_federation = { + pool_id = google_iam_workload_identity_pool.ingestion_auth_pool.workload_identity_pool_id + pool_provider_id = google_iam_workload_identity_pool_provider.ingestion_auth_pool_provider.workload_identity_pool_provider_id + project_number = data.google_project.project.number + } + email = google_service_account.push_auth.email + } + } + }) +} \ No newline at end of file diff --git a/modules/integrations/pub-sub/organizational.tf b/modules/integrations/pub-sub/organizational.tf new file mode 100644 index 0000000..b721906 --- /dev/null +++ b/modules/integrations/pub-sub/organizational.tf @@ -0,0 +1,95 @@ +#----------------------------------------------------------------------------------------- +# Fetch the data sources +#----------------------------------------------------------------------------------------- + +data "google_organization" "org" { + count = var.is_organizational ? 1 : 0 + domain = var.organization_domain +} + +#----------------------------------------------------------------------------------------- +# Audit Logs +#----------------------------------------------------------------------------------------- + +resource "google_organization_iam_audit_config" "audit_config" { + for_each = var.is_organizational ? local.audit_log_config : {} + + org_id = data.google_organization.org[0].org_id + service = each.key + + dynamic "audit_log_config" { + for_each = each.value.log_config + iterator = log_config + content { + log_type = log_config.value.log_type + exempted_members = log_config.value.exempted_members + } + } +} + +#----------------------------------------------------------------------------------------- +# Sink +#----------------------------------------------------------------------------------------- + +resource "google_logging_organization_sink" "ingestion_sink" { + count = var.is_organizational ? 1 : 0 + + name = "${google_pubsub_topic.ingestion_topic.name}_sink" + description = "Sysdig sink to direct the AuditLogs to the PubSub topic used for data gathering" + org_id = data.google_organization.org[0].org_id + + # NOTE: The target destination is a PubSub topic + destination = "pubsub.googleapis.com/projects/${var.project_id}/topics/${google_pubsub_topic.ingestion_topic.name}" + filter = var.ingestion_sink_filter + + # Dynamic block to exclude logs from ingestion + dynamic "exclusions" { + for_each = var.exclude_logs_filter + content { + name = exclusions.value.name + description = exclusions.value.description + filter = exclusions.value.filter + disabled = exclusions.value.disabled + } + } + + # NOTE: The include_children attribute is set to true in order to ingest data + # even from potential sub-organizations + include_children = true +} + +# creating custom role with organization-level permissions to access data ingestion resources +resource "google_organization_iam_custom_role" "custom_ingestion_auth_role" { + count = var.is_organizational ? 1 : 0 + + org_id = data.google_organization.org[0].org_id + role_id = "${local.role_name}Org${local.suffix}" + title = "Sysdigcloud Ingestion Org Auth Role" + description = "A Role providing the required permissions for Sysdig Backend to read cloud resources created for data ingestion" + permissions = [ + "pubsub.topics.get", + "pubsub.topics.list", + "pubsub.subscriptions.get", + "pubsub.subscriptions.list", + "logging.sinks.get", + "logging.sinks.list", + ] +} + +# adding custom role with organization-level permissions to the service account for auth +resource "google_organization_iam_member" "custom" { + count = var.is_organizational ? 1 : 0 + + org_id = data.google_organization.org[0].org_id + role = google_organization_iam_custom_role.custom_ingestion_auth_role[0].id + member = "serviceAccount:${google_service_account.push_auth.email}" +} + +# adding ciem role with permissions to the service account for org +resource "google_organization_iam_member" "identity_mgmt" { + for_each = var.is_organizational ? toset(["roles/recommender.viewer", "roles/iam.serviceAccountViewer", "roles/iam.organizationRoleViewer", "roles/container.clusterViewer", "roles/compute.viewer"]) : [] + + org_id = data.google_organization.org[0].org_id + role = each.key + member = "serviceAccount:${google_service_account.push_auth.email}" +} \ No newline at end of file diff --git a/modules/integrations/pub-sub/outputs.tf b/modules/integrations/pub-sub/outputs.tf new file mode 100644 index 0000000..a1f7b73 --- /dev/null +++ b/modules/integrations/pub-sub/outputs.tf @@ -0,0 +1,5 @@ +output "pubsub_datasource_component_id" { + value = "${sysdig_secure_cloud_auth_account_component.gcp_pubsub_datasource.type}/${sysdig_secure_cloud_auth_account_component.gcp_pubsub_datasource.instance}" + description = "Component identifier of Webhook Datasource integration created in Sysdig Backend for Log Ingestion" + depends_on = [sysdig_secure_cloud_auth_account_component.gcp_pubsub_datasource] +} \ No newline at end of file diff --git a/modules/integrations/pub-sub/variables.tf b/modules/integrations/pub-sub/variables.tf new file mode 100644 index 0000000..6cf397b --- /dev/null +++ b/modules/integrations/pub-sub/variables.tf @@ -0,0 +1,103 @@ +variable "project_id" { + type = string + description = "(Required) Target Project identifier provided by the customer" +} + +variable "labels" { + type = map(string) + description = "(Optional) Labels to be associated with Sysdig-originated resources" + default = { + originator = "sysdig" + } +} + +variable "ack_deadline_seconds" { + type = number + description = "(Optional) Maximum time in seconds after Sysdig's subscriber receives a message before the subscriber should acknowledge the message" + default = 60 +} + +variable "message_retention_duration" { + type = string + description = "(Optional) How long unacknowledged messages are retained in Sysdig's subscription backlog, from the moment a message is published" + default = "604800s" +} + +variable "max_delivery_attempts" { + type = number + description = "(Optional) Number of attempts redelivering missed messages from the deadletter topic to the main one" + default = 5 +} + +variable "minimum_backoff" { + type = string + description = "(Optional) Minimum backoff time for exponential backoff of the push subscription retry policy" + default = "10s" +} + +variable "maximum_backoff" { + type = string + description = "(Optional) Maximum backoff time for exponential backoff of the push subscription retry policy" + default = "600s" +} + +variable "is_organizational" { + description = "(Optional) Set this field to 'true' to deploy secure-for-cloud to a GCP Organization." + type = bool + default = false +} + +variable "organization_domain" { + type = string + description = "(Optional) Organization domain. e.g. sysdig.com" + default = "" +} + +variable "suffix" { + type = string + description = "Suffix to uniquely identify resources during multiple installs. If not provided, random value is autogenerated" + default = null +} + +variable "audit_log_config" { + description = "List of services and their audit log configurations to be ingested. Default is to ingest all logs." + type = list(object({ + service = string, + log_config = list(object({ + log_type = string, + exempted_members = optional(list(string)) + })) + })) + default = [ + { + service = "allServices" + log_config = [ + { log_type = "ADMIN_READ" }, + { log_type = "DATA_READ" }, + { log_type = "DATA_WRITE" } + ] + } + ] +} + +variable "exclude_logs_filter" { + description = "Filter to exclude logs from ingestion. Default is to ingest all google.cloud.audit.AuditLog logs. with no exclusions." + type = list(object({ + name = string, + description = optional(string), + filter = string, + disabled = optional(bool) + })) + default = [] +} + +variable "ingestion_sink_filter" { + type = string + description = "Filter the Logging Sink is set up with. Default is to ingests AuditLogs" + default = "protoPayload.@type = \"type.googleapis.com/google.cloud.audit.AuditLog\"" +} + +variable "sysdig_secure_account_id" { + type = string + description = "ID of the Sysdig Cloud Account to enable to enable Pub Sub integration for (incase of organization, ID of the Sysdig management account)" +} \ No newline at end of file diff --git a/modules/integrations/pub-sub/versions.tf b/modules/integrations/pub-sub/versions.tf new file mode 100644 index 0000000..adb6e1a --- /dev/null +++ b/modules/integrations/pub-sub/versions.tf @@ -0,0 +1,18 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers { + google = { + source = "hashicorp/google" + version = ">= 4.21.0" + } + sysdig = { + source = "sysdiglabs/sysdig" + version = ">= 1.34.0" + } + random = { + source = "hashicorp/random" + version = ">= 3.1" + } + } +} \ No newline at end of file diff --git a/test/examples/modular_organization/pub-sub.tf b/test/examples/modular_organization/pub-sub.tf new file mode 100644 index 0000000..7cbaad9 --- /dev/null +++ b/test/examples/modular_organization/pub-sub.tf @@ -0,0 +1,28 @@ +#--------------------------------------------------------------------------------------------- +# Ensure installation flow for foundational onboarding has been completed before +# installing additional Sysdig features. +#--------------------------------------------------------------------------------------------- + +module "pub-sub" { + source = "../../../modules/integrations/pub-sub" + 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" "threat_detection" { + account_id = module.onboarding.sysdig_secure_account_id + type = "FEATURE_SECURE_THREAT_DETECTION" + enabled = true + components = [ module.pub-sub.pubsub_datasource_component_id ] + depends_on = [ module.pub-sub ] +} + +resource "sysdig_secure_cloud_auth_account_feature" "identity_entitlement" { + account_id = module.onboarding.sysdig_secure_account_id + type = "FEATURE_SECURE_IDENTITY_ENTITLEMENT" + enabled = true + components = [module.pub-sub.pubsub_datasource_component_id] + depends_on = [sysdig_secure_cloud_auth_account_feature.config_posture, module.pub-sub] +} \ No newline at end of file diff --git a/test/examples/modular_single_project/pub-sub.tf b/test/examples/modular_single_project/pub-sub.tf new file mode 100644 index 0000000..dbe4c43 --- /dev/null +++ b/test/examples/modular_single_project/pub-sub.tf @@ -0,0 +1,26 @@ +#--------------------------------------------------------------------------------------------- +# Ensure installation flow for foundational onboarding has been completed before +# installing additional Sysdig features. +#--------------------------------------------------------------------------------------------- + +module "pub-sub" { + source = "../../../modules/integrations/pub-sub" + project_id = module.onboarding.project_id + sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id +} + +resource "sysdig_secure_cloud_auth_account_feature" "threat_detection" { + account_id = module.onboarding.sysdig_secure_account_id + type = "FEATURE_SECURE_THREAT_DETECTION" + enabled = true + components = [ module.pub-sub.pubsub_datasource_component_id ] + depends_on = [ module.pub-sub ] +} + +resource "sysdig_secure_cloud_auth_account_feature" "identity_entitlement" { + account_id = module.onboarding.sysdig_secure_account_id + type = "FEATURE_SECURE_IDENTITY_ENTITLEMENT" + enabled = true + components = [module.pub-sub.pubsub_datasource_component_id] + depends_on = [sysdig_secure_cloud_auth_account_feature.config_posture, module.pub-sub] +} \ No newline at end of file