From c674d2bcfb2d50ea20752d1b52e474f7e9fa99e3 Mon Sep 17 00:00:00 2001 From: Marat Salakhutdinov Date: Mon, 20 Jan 2025 19:05:32 -0500 Subject: [PATCH] add accounts list onboarding option for agentless scanning module --- modules/agentless-scanning/README.md | 2 ++ modules/agentless-scanning/organizational.tf | 36 +++++++++++++++++--- modules/agentless-scanning/variables.tf | 6 ++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/modules/agentless-scanning/README.md b/modules/agentless-scanning/README.md index b14b5d7..5b8710f 100644 --- a/modules/agentless-scanning/README.md +++ b/modules/agentless-scanning/README.md @@ -37,6 +37,7 @@ No modules. |------|------| | [aws_cloudformation_stack_set.ou_resources_stackset](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set) | resource | | [aws_cloudformation_stack_set.primary_acc_stackset](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set) | resource | +| [aws_cloudformation_stack_set_instance.accounts_stackset_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance) | resource | | [aws_cloudformation_stack_set_instance.ou_stackset_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance) | resource | | [aws_cloudformation_stack_set_instance.primary_acc_stackset_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance) | resource | | [aws_iam_role.scanning_stackset_admin_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | @@ -62,6 +63,7 @@ No modules. | [kms\_key\_deletion\_window](#input\_kms\_key\_deletion\_window) | Deletion window for shared KMS key | `number` | `7` | no | | [mgt\_stackset](#input\_mgt\_stackset) | (Optional) Indicates if the management stackset should be deployed | `bool` | `true` | no | | [name](#input\_name) | The name of the installation. Assigned to most child resource(s) | `string` | `"sysdig-secure-scanning"` | no | +| [org\_accounts](#input\_org\_accounts) | (Optional) List of Account IDs in which to setup Agentless Scanning. By default, Agentless Scanning will be setup in all accounts within the Organization. This field is ignored if `is_organizational = false`. If this field is set `org_units` variable is ignored and resources are deployed only to accounts listed within this variable with addition of management account of the organization | `set(string)` | `[]` | no | | [org\_units](#input\_org\_units) | (Optional) List of Organization Unit IDs in which to setup Agentless Scanning. By default, Agentless Scanning will be setup in all accounts within the Organization. This field is ignored if `is_organizational = false` | `set(string)` | `[]` | no | | [regions](#input\_regions) | (Optional) List of regions in which to install Agentless Scanning | `set(string)` | `[]` | no | | [scanning\_account\_id](#input\_scanning\_account\_id) | The identifier of the account that will receive volume snapshots | `string` | `"878070807337"` | no | diff --git a/modules/agentless-scanning/organizational.tf b/modules/agentless-scanning/organizational.tf index c02ea6b..45faaa4 100644 --- a/modules/agentless-scanning/organizational.tf +++ b/modules/agentless-scanning/organizational.tf @@ -12,7 +12,9 @@ data "aws_organizations_organization" "org" { } locals { - organizational_unit_ids = var.is_organizational && length(var.org_units) == 0 ? [for root in data.aws_organizations_organization.org[0].roots : root.id] : toset(var.org_units) + root_org_id = [for root in data.aws_organizations_organization.org[0].roots : root.id] + organizational_unit_ids = var.is_organizational && length(var.org_units) == 0 ? (length(var.org_accounts) == "0" ? local.root_org_id : []) : toset(var.org_units) + account_ids = var.is_organizational && length(var.org_accounts) == 0 ? [] : setunion(toset(var.org_accounts),[data.aws_caller_identity.current.account_id]) } #----------------------------------------------------------------------------------------------------------------------- @@ -67,7 +69,7 @@ Resources: Statement: - Sid: "Read" Effect: "Allow" - Action: + Action: - "ec2:Describe*" Resource: "*" Condition: @@ -158,7 +160,7 @@ Resources: - Sid: "SysdigAllowKms" Effect: "Allow" Principal: - AWS: + AWS: - "arn:aws:iam::${data.sysdig_secure_agentless_scanning_assets.assets.aws.account_id}:root" - !GetAtt ScanningRole.Arn Action: @@ -173,7 +175,7 @@ Resources: - Sid: "AllowCustomerManagement" Effect: "Allow" Principal: - AWS: + AWS: - !Sub "arn:aws:iam::$${AWS::AccountId}:root" - "${local.caller_arn}" - !Sub "arn:aws:iam::$${AWS::AccountId}:role/aws-service-role/member.org.stacksets.cloudformation.amazonaws.com/AWSServiceRoleForCloudFormationStackSetsOrgMember" @@ -191,7 +193,7 @@ TEMPLATE # stackset instance to deploy resources for agentless scanning, in all regions of each account in all organization units resource "aws_cloudformation_stack_set_instance" "ou_stackset_instance" { - for_each = var.is_organizational ? local.region_set : toset([]) + for_each = var.is_organizational ? (length(local.organizational_unit_ids) > 0 ? local.region_set : toset([])) : toset([]) region = each.key stack_set_name = aws_cloudformation_stack_set.ou_resources_stackset[0].name @@ -211,3 +213,27 @@ resource "aws_cloudformation_stack_set_instance" "ou_stackset_instance" { delete = var.timeout } } + +resource "aws_cloudformation_stack_set_instance" "accounts_stackset_instance" { + for_each = var.is_organizational ? (length(local.account_ids) > 0 ? local.region_set : toset([])) : toset([]) + region = each.key + + stack_set_name = aws_cloudformation_stack_set.ou_resources_stackset[0].name + deployment_targets { + organizational_unit_ids = local.root_org_id + accounts = local.account_ids + account_filter_type = "INTERSECTION" + } + 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 + } +} \ No newline at end of file diff --git a/modules/agentless-scanning/variables.tf b/modules/agentless-scanning/variables.tf index c8fe4eb..106c270 100644 --- a/modules/agentless-scanning/variables.tf +++ b/modules/agentless-scanning/variables.tf @@ -36,6 +36,12 @@ variable "org_units" { default = [] } +variable "org_accounts" { + description = "(Optional) List of Account IDs in which to setup Agentless Scanning. By default, Agentless Scanning will be setup in all accounts within the Organization. This field is ignored if `is_organizational = false`. If this field is set `org_units` variable is ignored and resources are deployed only to accounts listed within this variable with addition of management account of the organization" + type = set(string) + default = [] +} + variable "regions" { description = "(Optional) List of regions in which to install Agentless Scanning" type = set(string)