-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Modular Event Bridge for Log Ingestion (single) (#4)
* Add support for Modular Event Bridge for Log Ingestion (single) Change summary: ---------------- - Added the module as an integration module since it is feature agnostic and can be used for shared integrations. - Added the respective tf files for single onboarding case - Added test example for event-bridge integration (single) Testing: --------- Validated the changes with single onboarding of actual accounts on AWS. * Add README and minor fixes * Remove provider block in snippet As suspected, the provider block for primary region is no longer needed in event bridge snippets. The foundational snippet takes care of it. Was able to test this end to end. * Update README and remove delegated_admin check for single installs * Fix ciem feature dependency The feature resource should depend on the respective features and not the modules. Fixing that. Tested this with a terraform run with apply & destroy.
- Loading branch information
1 parent
53fb187
commit 4859850
Showing
7 changed files
with
526 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# AWS Event Bridge Module | ||
|
||
This Module creates the resources required to send CloudTrail logs to Sysdig via AWS EventBridge for Log Ingestion. These resources enable Threat Detection in the given single account, or AWS Organization. | ||
|
||
The following resources will be created in each instrumented account through CloudFormation StackSet in provided regions: | ||
- An `EventBridge Rule` that captures all CloudTrail events from the defaul EventBridge Bus | ||
- An `EventBridge Target` that sends these events to an EventBridge Bus is Sysdig's AWS Account | ||
- An `IAM Role` and associated policies that gives the EventBridge Bus in the source account permission to call PutEvent on the EventBridge Bus in Sysdig's Account. | ||
|
||
When run in Organizational mode, this module will be deployed via CloudFormation StackSets that should be created in the management account. They will create the above resources in each account in the organization, | ||
and automatically in any member accounts that are later added to the organization. If a delegated admin account is used, only SERVICE_MANAGED stacksets will be created in the delegated admin account, | ||
responsible for creating the above resources in each account in the organization. | ||
|
||
This module will also deploy an Event Bridge Component in Sysdig Backend for onboarded Sysdig Cloud Account. | ||
|
||
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.60.0 | | ||
| <a name="requirement_sysdig"></a> [sysdig](#requirement\_sysdig) | | ||
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.1 | | ||
|
||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.60.0 | | ||
|
||
## Modules | ||
|
||
No modules. | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [random_id.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | | ||
| [aws_iam_role.event_bus_invoke_remote_event_bus](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [aws_iam_role.event_bus_stackset_admin_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [aws_iam_role.event_bus_stackset_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [aws_cloudformation_stack_set.single-acc-stackset](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set) | resource | | ||
| [aws_cloudformation_stack_set_instance.single_acc_stackset_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance) | resource | | ||
| [sysdig_secure_cloud_auth_account_component.aws_event_bridge](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/resources/secure_cloud_auth_account_component) | resource | | ||
| [aws_iam_policy_document.cloud_trail_events](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | ||
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | ||
| [sysdig_secure_cloud_ingestion_assets.assets](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/data-sources/secure_cloud_ingestion_assets) | data source | | ||
| [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_tenant_external_id.external_id](https://registry.terraform.io/providers/sysdiglabs/sysdig/latest/docs/data-sources/secure_tenant_external_id) | data source | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_event_pattern"></a> [event\_pattern](#input\_event\_pattern) | Event pattern for CloudWatch Event Rule | `string` | `"{\n \"detail-type\": [\n \"AWS API Call via CloudTrail\",\n \"AWS Console Sign In via CloudTrail\",\n \"AWS Service Event via CloudTrail\",\n \"Object Access Tier Changed\",\n \"Object ACL Updated\",\n \"Object Created\",\n \"Object Deleted\",\n \"Object Restore Completed\",\n \"Object Restore Expired\",\n \"Object Restore Initiated\",\n \"Object Storage Class Changed\",\n \"Object Tags Added\",\n \"Object Tags Deleted\",\n \"GuardDuty Finding\"\n ]\n}\n"` | no | | ||
| <a name="input_failure_tolerance_percentage"></a> [failure\_tolerance\_percentage](#input\_failure\_tolerance\_percentage) | The percentage of accounts, per Region, for which stack operations can fail before AWS CloudFormation stops the operation in that Region | `number` | `90` | no | | ||
| <a name="input_is_organizational"></a> [is\_organizational](#input\_is\_organizational) | (Optional) Set this field to 'true' to deploy EventBridge to an AWS Organization (Or specific OUs) | `bool` | `false` | no | | ||
| <a name="input_mgt_stackset"></a> [mgt\_stackset](#input\_mgt\_stackset) | (Optional) Indicates if the management stackset should be deployed | `bool` | `true` | no | | ||
| <a name="input_name"></a> [name](#input\_name) | (Optional) Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sysdig-secure-events"` | no | | ||
| <a name="input_org_units"></a> [org\_units](#input\_org\_units) | (Optional) List of Organization Unit IDs in which to setup EventBridge. By default, EventBridge will be setup in all accounts within the Organization. This field is ignored if `is_organizational = false` | `set(string)` | `[]` | no | | ||
| <a name="input_regions"></a> [regions](#input\_regions) | (Optional) List of regions in which to setup EventBridge. By default, current region is selected | `set(string)` | `[]` | no | | ||
| <a name="input_rule_state"></a> [rule\_state](#input\_rule\_state) | State of the rule. When state is ENABLED, the rule is enabled for all events except those delivered by CloudTrail. To also enable the rule for events delivered by CloudTrail, set state to ENABLED\_WITH\_ALL\_CLOUDTRAIL\_MANAGEMENT\_EVENTS. | `string` | `"ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS"` | no | | ||
| <a name="input_stackset_admin_role_arn"></a> [stackset\_admin\_role\_arn](#input\_stackset\_admin\_role\_arn) | (Optional) stackset admin role to run SELF\_MANAGED stackset | `string` | `""` | no | | ||
| <a name="input_stackset_execution_role_name"></a> [stackset\_execution\_role\_name](#input\_stackset\_execution\_role\_name) | (Optional) stackset execution role name to run SELF\_MANAGED stackset | `string` | `""` | no | | ||
| <a name="auto_create_stackset_roles"></a> [auto\_create\_stackset\_roles](#input\_auto\_create\_stackset\_roles) | Whether to auto create the custom stackset roles to run SELF_MANAGED stackset | `bool` | `true` | no | | ||
| <a name="input_tags"></a> [tags](#input\_tags) | (Optional) Tags to be attached to all Sysdig resources. | `map(string)` | <pre>{<br> "product": "sysdig-secure-for-cloud"<br>}</pre> | no | | ||
| <a name="input_timeout"></a> [timeout](#input\_timeout) | Default timeout values for create, update, and delete operations | `string` | `"30m"` | no | | ||
| <a name="delegated_admin"></a> [delegated_admin](#input\_delegated\_admin) | Whether to create the resources using an delegated admin account | `bool` | `false` | no | | ||
| <a name="input_sysdig_secure_account_id"></a> [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` | n/a | yes | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_event_bridge_component_id"></a> [event\_bridge\_component\_id](#output\_event\_bridge\_component\_id) | Component identifier of Event Bridge integration created in Sysdig Backend for Log Ingestion | | ||
<!-- 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
# For both Single Account and Organizational installs, resources are created using CloudFormation StackSet. | ||
# For Organizational installs, see organizational.tf. | ||
# | ||
# For single installs, the resources in this file are used to instrument the singleton account, whether it is a management account or a | ||
# member account. (delegated admin account is a noop here for single installs) | ||
# | ||
# For organizational installs, resources in this file get created for management account only. (because service-managed stacksets do not | ||
# include the management account they are create in, even if this account is within the target Organization). | ||
# If a delegated admin account is used (determined via delegated_admin flag), resources will skip creation. This is because we don't want | ||
# to create these stacksets if user provides a delegated admin account instead of management account. | ||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
#----------------------------------------------------------------------------------------- | ||
# Fetch the data sources | ||
#----------------------------------------------------------------------------------------- | ||
data "aws_caller_identity" "current" {} | ||
|
||
data "sysdig_secure_cloud_ingestion_assets" "assets" {} | ||
|
||
data "sysdig_secure_trusted_cloud_identity" "trusted_identity" { | ||
cloud_provider = "aws" | ||
} | ||
|
||
data "sysdig_secure_tenant_external_id" "external_id" {} | ||
|
||
#----------------------------------------------------------------------------------------- | ||
# These locals indicate the region list passed. | ||
#----------------------------------------------------------------------------------------- | ||
locals { | ||
region_set = toset(var.regions) | ||
} | ||
|
||
#----------------------------------------------------------------------------------------- | ||
# Generate a unique name for resources using random suffix and account ID hash | ||
#----------------------------------------------------------------------------------------- | ||
locals { | ||
account_id_hash = substr(md5(data.aws_caller_identity.current.account_id), 0, 4) | ||
eb_resource_name = "${var.name}-${random_id.suffix.hex}-${local.account_id_hash}" | ||
} | ||
|
||
#----------------------------------------------------------------------------------------------------------------------- | ||
# A random resource is used to generate unique Event Bridge name suffix for resources. | ||
# This prevents conflicts when recreating an Event Bridge resources with the same name. | ||
#----------------------------------------------------------------------------------------------------------------------- | ||
resource "random_id" "suffix" { | ||
byte_length = 3 | ||
} | ||
|
||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
# Self-managed stacksets require pair of StackSetAdministrationRole & StackSetExecutionRole IAM roles with self-managed permissions. | ||
# | ||
# If auto_create_stackset_roles is true, terraform will create this IAM Admin role in the source account with permissions to create | ||
# stacksets. If false, and values for stackset Admin role ARN is provided stackset will use it, else AWS will look for | ||
# predefined/default AWSCloudFormationStackSetAdministrationRole. | ||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "aws_iam_role" "event_bus_stackset_admin_role" { | ||
count = !var.auto_create_stackset_roles ? 0 : 1 | ||
name = "AWSCloudFormationStackSetAdministrationRoleForEB" | ||
tags = var.tags | ||
|
||
assume_role_policy = <<EOF | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Action": "sts:AssumeRole", | ||
"Principal": { | ||
"Service": "cloudformation.amazonaws.com" | ||
}, | ||
"Effect": "Allow" | ||
} | ||
] | ||
} | ||
EOF | ||
managed_policy_arns = ["arn:aws:iam::aws:policy/AWSCloudFormationFullAccess"] | ||
} | ||
|
||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
# Self-managed stacksets require pair of StackSetAdministrationRole & StackSetExecutionRole IAM roles with self-managed permissions. | ||
# | ||
# If auto_create_stackset_roles is true, terraform will create this IAM Admin role in the source account with permissions to create | ||
# stacksets, Event Bridge resources and trust relationship to CloudFormation service. If false, and values for stackset Execution role | ||
# name is provided stackset will use it, else AWS will look for predefined/default AWSCloudFormationStackSetExecutionRole. | ||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "aws_iam_role" "event_bus_stackset_execution_role" { | ||
count = !var.auto_create_stackset_roles ? 0 : 1 | ||
name = "AWSCloudFormationStackSetExecutionRoleForEB" | ||
tags = var.tags | ||
|
||
assume_role_policy = <<EOF | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Action": "sts:AssumeRole", | ||
"Principal": { | ||
"AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${aws_iam_role.event_bus_stackset_admin_role[0].name}" | ||
}, | ||
"Effect": "Allow", | ||
"Condition": {} | ||
} | ||
] | ||
} | ||
EOF | ||
managed_policy_arns = [ | ||
"arn:aws:iam::aws:policy/AWSCloudFormationFullAccess", | ||
"arn:aws:iam::aws:policy/AmazonEventBridgeFullAccess" | ||
] | ||
} | ||
|
||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
# These resources create an IAM role in the source account with permissions to call PutEvent on the EventBridge Bus in | ||
# Sysdig's AWS account. This role is attached to the EventBridge target that is created in the source account. | ||
# | ||
# This role will be used by EventBridge when sending events to Sysdig's EventBridge Bus. The EventBridge service is | ||
# given permission to assume this role. | ||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "aws_iam_role" "event_bus_invoke_remote_event_bus" { | ||
name = local.eb_resource_name | ||
tags = var.tags | ||
|
||
assume_role_policy = <<EOF | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Action": "sts:AssumeRole", | ||
"Principal": { | ||
"Service": "events.amazonaws.com" | ||
}, | ||
"Effect": "Allow" | ||
}, | ||
{ | ||
"Action": "sts:AssumeRole", | ||
"Principal": { | ||
"AWS": "${data.sysdig_secure_trusted_cloud_identity.trusted_identity.identity}" | ||
}, | ||
"Effect": "Allow", | ||
"Condition": { | ||
"StringEquals": { | ||
"sts:ExternalId": "${data.sysdig_secure_tenant_external_id.external_id.external_id}" | ||
} | ||
} | ||
} | ||
] | ||
} | ||
EOF | ||
inline_policy { | ||
name = local.eb_resource_name | ||
policy = data.aws_iam_policy_document.cloud_trail_events.json | ||
} | ||
} | ||
|
||
# IAM Policy Document used by EventBridge role for the cloudtrail events policy | ||
data "aws_iam_policy_document" "cloud_trail_events" { | ||
|
||
statement { | ||
sid = "CloudTrailEventsPut" | ||
|
||
effect = "Allow" | ||
|
||
actions = [ | ||
"events:PutEvents", | ||
] | ||
|
||
resources = [ | ||
data.sysdig_secure_cloud_ingestion_assets.assets.aws.eventBusARN, | ||
] | ||
} | ||
|
||
statement { | ||
sid = "CloudTrailEventRuleAccess" | ||
|
||
effect = "Allow" | ||
|
||
actions = [ | ||
"events:DescribeRule", | ||
"events:ListTargetsByRule", | ||
] | ||
|
||
resources = [ | ||
"arn:aws:events:*:*:rule/${local.eb_resource_name}", | ||
] | ||
} | ||
} | ||
|
||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
# This resource creates a stackset to set up an EventBridge Rule and Target to forward all CloudTrail events from the | ||
# source account to Sysdig. CloudTrail events are sent to the default EventBridge Bus in the source account automatically. | ||
# | ||
# Rule captures all events from CloudTrail in the source account. | ||
# Target forwards all CloudTrail events to Sysdig's EventBridge Bus. | ||
# See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target#cross-account-event-bus-target | ||
# | ||
# Note: self-managed stacksets require pair of StackSetAdministrationRole & StackSetExecutionRole IAM roles with self-managed permissions | ||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "aws_cloudformation_stack_set" "single-acc-stackset" { | ||
name = join("-", [local.eb_resource_name, "EBRuleSingleAcc"]) | ||
tags = var.tags | ||
permission_model = "SELF_MANAGED" | ||
capabilities = ["CAPABILITY_NAMED_IAM"] | ||
administration_role_arn = var.auto_create_stackset_roles ? aws_iam_role.event_bus_stackset_admin_role[0].arn : var.stackset_admin_role_arn | ||
execution_role_name = var.auto_create_stackset_roles ? aws_iam_role.event_bus_stackset_execution_role[0].name : var.stackset_execution_role_name | ||
|
||
managed_execution { | ||
active = true | ||
} | ||
|
||
lifecycle { | ||
ignore_changes = [administration_role_arn] | ||
} | ||
|
||
template_body = templatefile("${path.module}/stackset_template_body.tpl", { | ||
name = local.eb_resource_name | ||
event_pattern = var.event_pattern | ||
rule_state = var.rule_state | ||
target_event_bus_arn = data.sysdig_secure_cloud_ingestion_assets.assets.aws.eventBusARN | ||
}) | ||
|
||
depends_on = [ | ||
aws_iam_role.event_bus_invoke_remote_event_bus, | ||
aws_iam_role.event_bus_stackset_admin_role, | ||
aws_iam_role.event_bus_stackset_execution_role | ||
] | ||
} | ||
|
||
// stackset instance to deploy rule in all regions of single account | ||
resource "aws_cloudformation_stack_set_instance" "single_acc_stackset_instance" { | ||
for_each = local.region_set | ||
region = each.key | ||
stack_set_name = aws_cloudformation_stack_set.single-acc-stackset[0].name | ||
|
||
operation_preferences { | ||
max_concurrent_percentage = 100 | ||
failure_tolerance_percentage = var.failure_tolerance_percentage | ||
concurrency_mode = "SOFT_FAILURE_TOLERANCE" | ||
region_concurrency_type = "PARALLEL" | ||
} | ||
|
||
timeouts { | ||
create = var.timeout | ||
update = var.timeout | ||
delete = var.timeout | ||
} | ||
} | ||
|
||
#----------------------------------------------------------------------------------------------------------------------------------------- | ||
# Call Sysdig Backend to add the event-bridge 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" "aws_event_bridge" { | ||
account_id = var.sysdig_secure_account_id | ||
type = "COMPONENT_EVENT_BRIDGE" | ||
instance = "secure-runtime" | ||
version = "v0.1.0" | ||
event_bridge_metadata = jsonencode({ | ||
aws = { | ||
role_name = local.eb_resource_name | ||
rule_name = local.eb_resource_name | ||
#TODO: regions once support added | ||
} | ||
}) | ||
} |
Oops, something went wrong.