This file of code supplements the Expel knowledge base article for connecting ControlTower to Workbench. Refer to that article to know when you need cash code block. Step 1 { "AWSTemplateFormatVersion": "2010-09-09", "Parameters": { "WorkbenchExternalID": { "Description": "The UUID associated to your organization in Expel Workbench", "Type": "String" } }, "Resources": { "IAMR": { "Type": "AWS::IAM::Role", "Properties": { "ManagedPolicyArns": [ { "Ref": "IAMMP" } ], "RoleName": "ExpelAssumeRole", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::012205512454:user/ExpelCloudService" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": { "Ref": "WorkbenchExternalID" } } } } ] } } }, "IAMMP": { "Type": "AWS::IAM::ManagedPolicy", "Properties": { "ManagedPolicyName": "ExpelAccessPolicy", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudtrail:DescribeTrails", "cloudtrail:GetTrail", "cloudtrail:GetTrailStatus", "cloudtrail:ListTrails", "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:GetBucketNotification", "s3:GetEncryptionConfiguration", "s3:ListAllMyBuckets", "organizations:DescribeOrganization" ], "Resource": "*" } ] } } } } } Step 2 { "Sid": "Allow Expel to use this KMS key to decrypt logs", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam:::role/ExpelAssumeRole" }, "Action": "kms:Decrypt", "Resource": "*" } Step 4 *Option 1 code* { "AWSTemplateFormatVersion": "2010-09-09", "Parameters": { "S3LogBucketARN": { "Description": "The ARN for the S3 bucket in your Log Archive account storing your CloudTrail logs", "Type": "String" }, "CloudTrailKeyARN": { "Description": "The ARN for the CMK key configured on your CloudTrail", "Type": "String", "Default": "" } }, "Conditions": { "IsCloudTrailKeyARN": { "Fn::Not": [ { "Fn::Equals": [ { "Ref": "CloudTrailKeyARN" }, "" ] } ] } }, "Outputs": { "SqsURL": { "Description": "The SQS url path needed to complete setup of in Expel Workbench", "Value": { "Ref": "SQSQ" } }, "RoleARN": { "Description": "The IAM Role created in the log archive account needed to complete setup in Expel Workbench", "Value": { "Fn::Join": [ ":", [ "arn:aws:iam:", { "Ref": "AWS::AccountId" }, "role/ExpelAssumeRole" ] ] } } }, "Resources": { "KMSK": { "Type": "AWS::KMS::Key", "Properties": { "KeyPolicy": { "Version": "2012-10-17", "Id": "key-default-1", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": [ { "Fn::Join": [ ":", [ "arn:aws:iam:", { "Ref": "AWS::AccountId" }, "root" ] ] } ] }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow Expel to decrypt", "Effect": "Allow", "Principal": { "AWS": [ { "Fn::Join": [ ":", [ "arn:aws:iam:", { "Ref": "AWS::AccountId" }, "role/ExpelAssumeRole" ] ] } ] }, "Action": "kms:Decrypt", "Resource": "*" }, { "Sid": "Allow S3 to encrypt/decrypt", "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": [ "kms:GenerateDataKey*", "kms:Decrypt" ], "Resource": "*", "Condition": { "ArnEquals": { "aws:SourceArn": { "Ref": "S3LogBucketARN" } } } }, { "Sid": "Allow SNS to encrypt/decrypt", "Effect": "Allow", "Principal": { "Service": "sns.amazonaws.com" }, "Action": [ "kms:GenerateDataKey*", "kms:Decrypt" ], "Resource": "*", "Condition": { "ArnEquals": { "aws:SourceArn": { "Fn::Join": [ ":", [ "arn:aws:sns", { "Ref": "AWS::Region" }, { "Ref": "AWS::AccountId" }, "ExpelTopic" ] ] } } } } ] } } }, "KMSKA": { "Type": "AWS::KMS::Alias", "Properties": { "AliasName": "alias/ExpelResourcesKey", "TargetKeyId": { "Ref": "KMSK" } } }, "SQSQ": { "Type": "AWS::SQS::Queue", "Properties": { "QueueName": "ExpelQueue", "KmsMasterKeyId": { "Ref": "KMSK" } } }, "SNST": { "Type": "AWS::SNS::Topic", "Properties": { "TopicName": "ExpelTopic", "KmsMasterKeyId": { "Ref": "KMSK" } } }, "SNSTS": { "Type": "AWS::SNS::Subscription", "Properties": { "Protocol": "sqs", "Endpoint": { "Fn::GetAtt": [ "SQSQ", "Arn" ] }, "RawMessageDelivery": true, "TopicArn": { "Ref": "SNST" } } }, "SNSTP": { "Type": "AWS::SNS::TopicPolicy", "Properties": { "PolicyDocument": { "Version": "2012-10-17", "Id": "key-default-1", "Statement": [ { "Sid": "Allow S3 to publish messages", "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": "SNS:Publish", "Resource": { "Ref": "SNST" }, "Condition": { "ArnEquals": { "aws:SourceArn": { "Ref": "S3LogBucketARN" } } } } ] }, "Topics": [ { "Ref": "SNST" } ] } }, "SQSQP": { "Type": "AWS::SQS::QueuePolicy", "Properties": { "Queues": [ { "Ref": "SQSQ" } ], "PolicyDocument": { "Statement": [ { "Action": [ "SQS:SendMessage" ], "Effect": "Allow", "Principal": { "Service": "sns.amazonaws.com" }, "Resource": { "Fn::GetAtt": [ "SQSQ", "Arn" ] }, "Condition": { "ArnEquals": { "aws:SourceArn": { "Ref": "SNST" } } } } ] } } }, "IAMMP": { "Type": "AWS::IAM::ManagedPolicy", "Properties": { "Description": "Provides Expel limited access to specific s3, sns & sqs resources", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket", "sqs:DeleteMessage", "sqs:ReceiveMessage" ], "Resource": [ { "Fn::Join": [ "/", [ { "Ref": "S3LogBucketARN" }, "*" ] ] }, { "Fn::GetAtt": [ "SQSQ", "Arn" ] } ] }, { "Fn::If": [ "IsCloudTrailKeyARN", { "Effect": "Allow", "Action": "kms:Decrypt", "Resource": [ { "Ref": "CloudTrailKeyARN" } ] }, { "Ref": "AWS::NoValue" } ] } ] }, "ManagedPolicyName": "ExpelResourcesAccessPolicy", "Roles": [ "ExpelAssumeRole" ] } } } } *Option 2 code* { "Version": "2008-10-17", "Id": "expel-topic-policy-ID", "Statement": [ { "Sid": "expel-statement-ID", "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": "SNS:Publish", "Resource": "", "Condition": { "ArnEquals": { "aws:SourceArn": "" } } } ] } Step 5 { "Version": "2012-10-17", "Id": "YOUR_QUEUE_ARN/SQSDefaultPolicy", "Statement": [ { "Sid": "Sid1572965666162", "Effect": "Allow", "Principal": { "Service": "sns.amazonaws.com" }, "Action": "SQS:SendMessage", "Resource": "", "Condition": { "ArnEquals": { "aws:SourceArn": "" } } } ] } Step 7 { "Statement": [ { "Sid": "Allow Expel to use this KMS key to decrypt logs", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam:::role/" }, "Action": "kms:Decrypt", "Resource": "*" }, { "Sid": "Allow S3 to encrypt/decrypt", "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": [ "kms:GenerateDataKey*", "kms:Decrypt" ], "Resource": "*", "Condition": { "ArnEquals": { "aws:SourceArn": "" } } }, { "Sid": "Allow SNS to encrypt/decrypt", "Effect": "Allow", "Principal": { "Service": "sns.amazonaws.com" }, "Action": [ "kms:GenerateDataKey*", "kms:Decrypt" ], "Resource": "*", "Condition": { "ArnEquals": { "aws:SourceArn": "" } } } ] } Step 9 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket", "sqs:DeleteMessage", "sqs:ReceiveMessage" ], "Resource": [ "/*", "" ] }, { "Effect": "Allow", "Action": "kms:Decrypt", "Resource": "" } ] }