Skip to content

Commit

Permalink
Add CloudFormation Stackset required for enabling multi-account organ…
Browse files Browse the repository at this point in the history
…ization CloudTrail (#26)

### Added
- Auto-deployed CloudFormation StackSet resource when enabling organization trail
  • Loading branch information
ethanmil authored May 10, 2022
1 parent e2e5615 commit 124c624
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 25 deletions.
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Configures a CloudTrail stack (CloudTrail & S3 bucket) with a notification queue
```hcl
module "expel_aws_cloudtrail" {
source = "expel-io/cloudtrail/aws"
version = "1.1.1"
version = "1.2.0"
expel_customer_organization_guid = "Replace with your organization GUID from Expel Workbench"
region = "AWS region in which notification queue for CloudTrail will be created"
Expand All @@ -21,12 +21,14 @@ security device to enable Expel to begin monitoring your AWS environment.
## Permissions
The permissions allocated by this module allow Expel Workbench to perform investigations and get a broad understanding of your AWS footprint.

## Use Cases
1. Creating a new AWS CloudTrail for a single AWS account
2. Creating a new AWS CloudTrial for an AWS organization (Set [enable\_organization\_trail](#input\_enable\_organization\_trail) input to true)

## Limitations
1. Only supports onboarding a single AWS account, not an entire AWS Organization.
2. Will always create a new CloudTrail, does not support re-using an existing CloudTrail.
Will always create a new CloudTrail, does not support re-using an existing CloudTrail.

See https://support.expel.io/hc/en-us/articles/360061333154-AWS-CloudTrail-getting-started-guide for options if you
have an AWS Organization or already have a CloudTrail you want to re-use.
See https://support.expel.io/hc/en-us/articles/360061333154-AWS-CloudTrail-getting-started-guide for options if you have a CloudTrail you want to re-use.

<!-- begin-tf-docs -->
## Requirements
Expand All @@ -39,7 +41,8 @@ have an AWS Organization or already have a CloudTrail you want to re-use.

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.0.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 4.12.0 |
| <a name="provider_random"></a> [random](#provider\_random) | 3.1.3 |
## Inputs

| Name | Description | Type | Default | Required |
Expand All @@ -54,7 +57,7 @@ have an AWS Organization or already have a CloudTrail you want to re-use.
| <a name="input_enable_sqs_encryption"></a> [enable\_sqs\_encryption](#input\_enable\_sqs\_encryption) | Enable server-side encryption (SSE) of message content with SQS-owned encryption keys. | `bool` | `true` | no |
| <a name="input_expel_assume_role_session_name"></a> [expel\_assume\_role\_session\_name](#input\_expel\_assume\_role\_session\_name) | The session name Expel will use when authenticating. | `string` | `"ExpelCloudTrailServiceSession"` | no |
| <a name="input_expel_aws_account_arn"></a> [expel\_aws\_account\_arn](#input\_expel\_aws\_account\_arn) | Expel's AWS Account ARN to allow assuming role to gain CloudTrail access. | `string` | `"arn:aws:iam::012205512454:user/ExpelCloudService"` | no |
| <a name="input_prefix"></a> [prefix](#input\_prefix) | A prefix to group all Expel integration resources. | `string` | `"expel-aws-integration"` | no |
| <a name="input_prefix"></a> [prefix](#input\_prefix) | A prefix to group all Expel integration resources. | `string` | `"expel-aws-cloudtrail"` | no |
| <a name="input_queue_message_retention_days"></a> [queue\_message\_retention\_days](#input\_queue\_message\_retention\_days) | The visibility timeout for the queue. See: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html | `number` | `7` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A set of tags to group resources. | `map` | `{}` | no |
## Outputs
Expand All @@ -69,8 +72,11 @@ have an AWS Organization or already have a CloudTrail you want to re-use.

| Name | Type |
|------|------|
| [aws_cloudformation_stack_set.permeate_account_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set) | resource |
| [aws_cloudformation_stack_set_instance.permeate_account_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance) | resource |
| [aws_cloudtrail.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource |
| [aws_iam_policy.cloudtrail_manager_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_role.AWSCloudFormationStackSetAdministrationRole](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.expel_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.cloudtrail_manager_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_kms_key.cloudtrail_bucket_encryption_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
Expand All @@ -89,9 +95,14 @@ have an AWS Organization or already have a CloudTrail you want to re-use.
| [aws_s3_bucket_versioning.cloudtrail_bucket_versioning](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource |
| [aws_sqs_queue.cloudtrail_queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource |
| [aws_sqs_queue_policy.sqs_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource |
| [random_uuid.cloudtrail_bucket_name](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_iam_policy_document.AWSCloudFormationStackSetAdministrationRole_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.assume_role_iam_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cloudtrail_bucket_iam_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cloudtrail_key_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cloudtrail_manager_iam_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.sqs_bucket_iam_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_organizations_organization.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/organizations_organization) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
<!-- end-tf-docs -->
18 changes: 18 additions & 0 deletions aws.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
data "aws_organizations_organization" "current" {}

locals {
default_tags = {
"vendor" = "expel"
}

tags = merge(
var.tags,
local.default_tags,
)

region = data.aws_region.current.name
customer_aws_account_id = data.aws_caller_identity.current.account_id
customer_aws_organization_id = try(data.aws_organizations_organization.current.roots[0].id, "")
}
1 change: 1 addition & 0 deletions iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ data "aws_iam_policy_document" "cloudtrail_manager_iam_document" {
effect = "Allow"
}

# Note: This is a duplicate policy statement with CloudFormation StackSet "PermeateAccountPolicy"
# Allow Expel Workbench to gather information about AWS footprint
statement {
actions = [
Expand Down
33 changes: 33 additions & 0 deletions stackset.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
resource "aws_cloudformation_stack_set" "permeate_account_policy" {
count = var.enable_organization_trail ? 1 : 0

name = "PermeateAccountPolicy"
description = "Creates policies in all accounts of the organization for Expel to get basic read permissions of resources in order to investigate alerts"
permission_model = "SERVICE_MANAGED"
capabilities = ["CAPABILITY_NAMED_IAM"]

auto_deployment {
enabled = true
}

parameters = {
ExpelCustomerOrganizationGUID = var.expel_customer_organization_guid,
ExpelAssumeRoleARN = aws_iam_role.expel_assume_role.arn
}

template_body = local.stackset_template

tags = local.tags
}


resource "aws_cloudformation_stack_set_instance" "permeate_account_policy" {
count = var.enable_organization_trail ? 1 : 0

deployment_targets {
organizational_unit_ids = [local.customer_aws_organization_id]
}

region = local.region
stack_set_name = aws_cloudformation_stack_set.permeate_account_policy[0].name
}
89 changes: 89 additions & 0 deletions stackset_template.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Note: ExpelAccessPolicy is a duplicate policy statement with CloudTrail Manager IAM Policy
locals {
stackset_template = <<TEMPLATE
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters" : {
"ExpelCustomerOrganizationGUID" : {
"Type" : "String"
},
"ExpelAssumeRoleARN" : {
"Type" : "String"
}
},
"Resources": {
"IAMR7FYC": {
"Type": "AWS::IAM::Role",
"Properties": {
"ManagedPolicyArns": [
{
"Ref": "IAMMP12SQ7"
}
],
"RoleName": "ExpelRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": { "Ref": "ExpelAssumeRoleARN" }
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": { "Ref": "ExpelCustomerOrganizationGUID" }
}
}
}
]
}
}
},
"IAMMP12SQ7": {
"Type": "AWS::IAM::ManagedPolicy",
"Properties": {
"ManagedPolicyName": "ExpelAccessPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"config:GetDiscoveredResourceCounts",
"config:ListDiscoveredResources",
"ec2:DescribeInstances",
"ec2:DescribeRegions",
"ec2:DescribeSecurityGroups",
"ec2:DescribeVolumes",
"ecs:DescribeClusters",
"ecs:DescribeContainerInstances",
"ecs:DescribeTaskDefinition",
"ecs:ListClusters",
"ecs:ListContainerInstances",
"ecs:ListTaskDefinitions",
"eks:DescribeCluster",
"eks:ListClusters",
"iam:Get*",
"iam:List*",
"lambda:GetFunction",
"lambda:ListFunctions",
"lightsail:GetInstances",
"lightsail:GetRegions",
"organizations:ListAccounts",
"rds:DescribeDBInstances",
"rds:ListTagsForResource",
"s3:ListAllMyBuckets"
],
"Resource": "*"
}
]
}
}
}
}
}
TEMPLATE
}
18 changes: 0 additions & 18 deletions terraform.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,3 @@ terraform {
}
required_version = ">= 1.1.0"
}

data "aws_region" "current" {}
data "aws_caller_identity" "current" {}

locals {
default_tags = {
"vendor" = "expel"
}

tags = merge(
var.tags,
local.default_tags,
)

region = data.aws_region.current.name
customer_aws_account_id = data.aws_caller_identity.current.account_id
}

0 comments on commit 124c624

Please sign in to comment.