diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0de86e6e..663468c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,7 +45,6 @@
All notable changes to this project will be documented in this file.
---
-
## 2023-10-23
Updated [Firewall Manager](https://github.com/aws-samples/aws-security-reference-architecture-examples/tree/main/aws_sra_examples/solutions/firewall_manager/firewall_manager_org) solution to make AWS Control Tower optional.
diff --git a/README.md b/README.md
index bea4d5df..b928d440 100644
--- a/README.md
+++ b/README.md
@@ -146,6 +146,7 @@ _Note: The `Quick Setup` is not designed to be used with the `Easy Setup` proced
| [Inspector](aws_sra_examples/solutions/inspector/inspector_org) | Configure Inspector within a delegated admin account for all accounts and governed regions within the organization. | | |
| [Detective](aws_sra_examples/solutions/detective/detective) | The Detective Organization solution will automate enabling Amazon Detective by delegating administration to an account (e.g. Audit or Security Tooling) and configuring Detective for all the existing and future AWS Organization accounts. **Note:** As of 06/07/2023, this solution is not included in the quick setup (it will be in a future code release) | |
- AWS Control Tower
- [GuardDuty](aws_sra_examples/solutions/guardduty/guardduty_org)
|
+
## Utils
- packaging_scripts/stage-solution.sh (Package and stage all the AWS SRA example solutions. For more information see [Staging script details](aws_sra_examples/docs/DOWNLOAD-AND-STAGE-SOLUTIONS.md#staging-script-details))
diff --git a/aws_sra_examples/easy_setup/customizations_for_aws_control_tower/manifest.yaml b/aws_sra_examples/easy_setup/customizations_for_aws_control_tower/manifest.yaml
index eb5cacdb..efa2d66b 100644
--- a/aws_sra_examples/easy_setup/customizations_for_aws_control_tower/manifest.yaml
+++ b/aws_sra_examples/easy_setup/customizations_for_aws_control_tower/manifest.yaml
@@ -194,7 +194,7 @@ resources:
# Inspector Solution
- parameter_key: pScanComponents
- parameter_value: 'EC2, ECR, LAMBDA'
+ parameter_value: 'EC2, ECR, LAMBDA, LAMBDA_CODE'
- parameter_key: pEcrRescanDuration
parameter_value: 'LIFETIME'
diff --git a/aws_sra_examples/easy_setup/templates/sra-easy-setup.yaml b/aws_sra_examples/easy_setup/templates/sra-easy-setup.yaml
index 1f47f6cb..f5d4d2a8 100644
--- a/aws_sra_examples/easy_setup/templates/sra-easy-setup.yaml
+++ b/aws_sra_examples/easy_setup/templates/sra-easy-setup.yaml
@@ -226,7 +226,7 @@ Metadata:
default: SRA Staging S3 Bucket Stack Name
pScanComponents:
- default: Comma separated list of scan components (EC2, ECR, LAMBDA)
+ default: Comma separated list of scan components (EC2, ECR, LAMBDA, LAMBDA_CODE)
pEcrRescanDuration:
default: ECR Rescan Duration
pDeployInspectorSolution:
@@ -522,8 +522,8 @@ Parameters:
Type: String
pScanComponents:
- AllowedValues: [EC2, ECR, LAMBDA]
- Default: EC2, ECR, LAMBDA
+ AllowedValues: [EC2, ECR, LAMBDA, LAMBDA_CODE]
+ Default: EC2, ECR, LAMBDA, LAMBDA_CODE
Description: Lambda Function Logging Level
Type: CommaDelimitedList
pEcrRescanDuration:
diff --git a/aws_sra_examples/modules/cloudtrail-org-module/templates/sra-cloudtrail-org-module-main.yaml b/aws_sra_examples/modules/cloudtrail-org-module/templates/sra-cloudtrail-org-module-main.yaml
new file mode 100644
index 00000000..7bca4764
--- /dev/null
+++ b/aws_sra_examples/modules/cloudtrail-org-module/templates/sra-cloudtrail-org-module-main.yaml
@@ -0,0 +1,1177 @@
+########################################################################
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: MIT-0
+########################################################################
+AWSTemplateFormatVersion: '2010-09-09'
+Description: Installs the AWS SRA cloudtrail solution. If needed, the AWS SRA common prerequisite solution is also installed. (sra-1u3sd7f8d)
+
+Metadata:
+ SRA:
+ Version: 1.0
+ Order: 1
+ AWS::CloudFormation::Interface:
+ ParameterGroups:
+ - Label:
+ default: General Properties
+ Parameters:
+ - pSRASolutionName
+ - pSRAHelperBucketNamePrefix
+ - pRandomParameter
+ - Label:
+ default: Landing Zone
+ Parameters:
+ - pControlTower
+ - pGovernedRegions
+ - pSecurityAccountId
+ - pLogArchiveAccountId
+ - pCreateAWSControlTowerExecutionRole
+ - Label:
+ default: SRA Code Repo
+ Parameters:
+ - pRepoURL
+ - pRepoBranch
+ - pTemplateURL
+ - Label:
+ default: CodeBuild
+ Parameters:
+ - pCodeBuildProjectName
+ - pCodeBuildProjectLambdaFunctionName
+ - pCodeBuildRoleName
+ - pCodeBuildProjectLambdaRoleName
+ - Label:
+ default: Lambda
+ Parameters:
+ - pCreateLambdaLogGroup
+ - pLambdaLogGroupKmsKey
+ - pLambdaLogGroupRetention
+ - pLambdaLogLevel
+ - pCheckForResourceLambdaFunctionName
+ - pGetCommonOutputsLambdaFunctionName
+ - pCheckForResourceLambdaRoleName
+
+ - Label:
+ default: CloudTrail
+ Parameters:
+ - pCloudTrailName
+ - pEnableDataEventsOnly
+ - pEnableLambdaDataEvents
+ - pEnableS3DataEvents
+ - pBucketNamePrefix
+ - pCloudTrailLogGroupKmsKey
+ - pCloudTrailLogGroupRetention
+ - pCreateCloudTrailLogGroup
+ - pOrganizationCloudTrailKeyAlias
+
+ ParameterLabels:
+ pSRASolutionName:
+ default: pSRASolutionName
+ pSRAHelperBucketNamePrefix:
+ default: pSRAHelperBucketNamePrefix
+ pRandomParameter:
+ default: pRandomParameter
+ pControlTower:
+ default: pControlTower
+ pGovernedRegions:
+ default: pGovernedRegions
+ pSecurityAccountId:
+ default: pSecurityAccountId
+ pLogArchiveAccountId:
+ default: pLogArchiveAccountId
+ pRepoURL:
+ default: pRepoURL
+ pRepoBranch:
+ default: pRepoBranch
+ pTemplateURL:
+ default: pTemplateURL
+ pCodeBuildProjectName:
+ default: pCodeBuildProjectName
+ pCodeBuildProjectLambdaFunctionName:
+ default: pCodeBuildProjectLambdaFunctionName
+ pCodeBuildRoleName:
+ default: pCodeBuildRoleName
+ pCodeBuildProjectLambdaRoleName:
+ default: pCodeBuildProjectLambdaRoleName
+ pCreateLambdaLogGroup:
+ default: pCreateLambdaLogGroup
+ pLambdaLogGroupKmsKey:
+ default: pLambdaLogGroupKmsKey
+ pLambdaLogGroupRetention:
+ default: pLambdaLogGroupRetention
+ pLambdaLogLevel:
+ default: pLambdaLogLevel
+ pCheckForResourceLambdaFunctionName:
+ default: pCheckForResourceLambdaFunctionName
+ pGetCommonOutputsLambdaFunctionName:
+ default: pGetCommonOutputsLambdaFunctionName
+ pCheckForResourceLambdaRoleName:
+ default: pCheckForResourceLambdaRoleName
+
+ pCloudTrailName:
+ default: CloudTrail Name
+ pEnableDataEventsOnly:
+ default: Enable Data Events Only
+ pEnableLambdaDataEvents:
+ default: Enable Lambda Data Events
+ pEnableS3DataEvents:
+ default: Enable S3 Data Events
+ pBucketNamePrefix:
+ default: S3 Log Bucket Name Prefix
+ pCloudTrailLogGroupKmsKey:
+ default: (Optional) CloudTrail CloudWatch Logs KMS Key
+ pCloudTrailLogGroupRetention:
+ default: CloudTrail Log Group Retention
+ pCreateCloudTrailLogGroup:
+ default: Create CloudTrail CloudWatch Log Group
+ pOrganizationCloudTrailKeyAlias:
+ default: Organization CloudTrail KMS Key Alias
+ pCreateAWSControlTowerExecutionRole:
+ default: Create AWS Control Tower Execution Role
+
+Parameters:
+ pRepoURL:
+ Default: https://github.com/aws-samples/aws-security-reference-architecture-examples.git
+ Description:
+ SRA Code Library Repository URL
+ Type: String
+ pRepoBranch:
+ Default: tags/v3.0.4
+ Description:
+ SRA Code Library Repository branch name. Can be used as branch or as tags (e.g. tags/v3.0.1)
+ Type: String
+ pTemplateURL:
+ Default: https://raw.githubusercontent.com/aws-samples/aws-security-reference-architecture-examples/v3.0.4/aws_sra_examples/modules/cloudtrail-org-module/templates/sra-cloudtrail-org-solution.yaml
+ Description:
+ SRA module solution template URL
+ Type: String
+
+ pControlTower:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description:
+ Indicates whether AWS Control Tower is deployed and being used for this AWS environment.
+ Type: String
+ pGovernedRegions:
+ AllowedPattern: '^(ct-regions)|((\b(?--. Example = sra-staging-123456789012-us-east-1.
+ Type: String
+ pSRAStagingS3BucketStackName:
+ AllowedValues: [sra-common-prerequisites-staging-s3-bucket]
+ Default: sra-common-prerequisites-staging-s3-bucket
+ Description:
+ SRA Common Prerequisite Staging S3 bucket stack name. This stack will be created by the SRA CodeBuild Project.
+ Type: String
+
+ pCreateLambdaLogGroup:
+ AllowedValues: ['Yes', 'No']
+ Default: 'No'
+ Description:
+ Indicates whether a CloudWatch Log Group should be explicitly created for the Lambda function, to allow for setting a Log Retention and/or KMS
+ Key for encryption.
+ Type: String
+ pDeployConfigManagementSolution:
+ AllowedValues: ['No', 'Already Deployed']
+ Default: 'Already Deployed'
+ Description: Deploy the AWS Config Management solution. Note, if solution was previously deployed, choose 'Already Deployed'.
+ Type: String
+ pDeploySecurityHubSolution:
+ AllowedValues: ['Yes', 'No']
+ Default: 'Yes'
+ Description: Deploy the Security Hub solution
+ Type: String
+ pLambdaLogGroupKmsKey:
+ AllowedPattern: '^$|^arn:(aws[a-zA-Z-]*){1}:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'
+ ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
+ Default: ''
+ Description:
+ (Optional) KMS Key ARN to use for encrypting the Lambda logs data. If empty, encryption is enabled with CloudWatch Logs managing the server-side
+ encryption keys.
+ Type: String
+ pLambdaLogGroupRetention:
+ AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
+ Default: 14
+ Description: Specifies the number of days you want to retain log events
+ Type: String
+ pLambdaLogLevel:
+ AllowedValues: [INFO, ERROR, DEBUG]
+ Default: INFO
+ Description: Lambda Function Logging Level
+ Type: String
+ pCreateAWSControlTowerExecutionRole:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Indicates whether the AWS Control Tower Execution role should be created.
+ Type: String
+
+ pDeployCloudTrailSolution:
+ AllowedValues: ['Yes', 'No']
+ Default: 'Yes'
+ Description: Deploy the CloudTrail solution
+ Type: String
+ pCloudTrailName:
+ AllowedPattern: '^[A-Za-z0-9][a-zA-Z0-9-\-_.]{2,127}$'
+ ConstraintDescription:
+ Contain only ASCII letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), or dashes (-) Start with a letter or number, and end with a
+ letter or number Be between 3 and 128 characters Have no adjacent periods, underscores or dashes. Names like my-_namespace and my--namespace are
+ invalid. Not be in IP address format (for example, 192.168.5.4)
+ Default: sra-org-trail
+ Description: CloudTrail name
+ Type: String
+ pEnableDataEventsOnly:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Only Enable Cloud Trail Data Events
+ Type: String
+ pEnableLambdaDataEvents:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Enable Cloud Trail Data Events for all Lambda functions
+ Type: String
+ pEnableS3DataEvents:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Enable Cloud Trail S3 Data Events for all buckets
+ Type: String
+ pBucketNamePrefix:
+ AllowedPattern: ^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$
+ ConstraintDescription:
+ S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
+ Default: sra-org-trail-logs
+ Description: S3 bucket prefix. The account and region will get added to the end. e.g. bucket-prefix-123456789012-us-east-1
+ Type: String
+ pCloudTrailLogGroupKmsKey:
+ AllowedPattern: ^$|^arn:(aws[a-zA-Z-]*){1}:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$
+ ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
+ Default: ''
+ Description:
+ (Optional) KMS Key ARN to use for encrypting the CloudTrail log group data. If empty, encryption is enabled with CloudWatch Logs managing the
+ server-side encryption keys.
+ Type: String
+ pCloudTrailLogGroupRetention:
+ AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
+ Default: 400
+ Description: Specifies the number of days you want to retain log events
+ Type: String
+ pCreateCloudTrailLogGroup:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description:
+ Indicates whether a CloudWatch Log Group should be created for the CloudTrail, to allow for setting a Log Retention and/or KMS Key for
+ encryption.
+ Type: String
+ pOrganizationCloudTrailKeyAlias:
+ Default: sra-cloudtrail-org-key
+ Description: Organization CloudTrail KMS Key Alias
+ Type: String
+
+Rules:
+ DeploySecurityHubSolutionValidation:
+ RuleCondition: !Equals [!Ref pDeploySecurityHubSolution, 'Yes']
+ Assertions:
+ - Assert: !Equals [!Ref pDeployConfigManagementSolution, 'Already Deployed']
+ AssertDescription:
+ "'Deploy the AWS Config Management Solution' parameter must be set to 'Already Deployed', if the security hub solution
+ is being deployed."
+
+Conditions:
+ cUsingKmsKey: !Not [!Equals [!Ref pLambdaLogGroupKmsKey, '']]
+ cUseGraviton: !Or
+ - !Equals [!Ref 'AWS::Region', ap-northeast-1]
+ - !Equals [!Ref 'AWS::Region', ap-south-1]
+ - !Equals [!Ref 'AWS::Region', ap-southeast-1]
+ - !Equals [!Ref 'AWS::Region', ap-southeast-2]
+ - !Equals [!Ref 'AWS::Region', eu-central-1]
+ - !Equals [!Ref 'AWS::Region', eu-west-1]
+ - !Equals [!Ref 'AWS::Region', eu-west-2]
+ - !Equals [!Ref 'AWS::Region', us-east-1]
+ - !Equals [!Ref 'AWS::Region', us-east-2]
+ - !Equals [!Ref 'AWS::Region', us-west-2]
+
+ cCommonPrerequisitesNotInstalled: !Equals [!Ref pCommonPrerequisitesInstalled, 'false']
+ cCreateLambdaLogGroup: !Equals [!Ref pCreateLambdaLogGroup, 'Yes']
+ cDeployCloudTrailSolution: !Equals [!Ref pDeployCloudTrailSolution, 'Yes']
+ cLambdaLogGrouOutput: !And
+ - !Condition cCommonPrerequisitesNotInstalled
+ - !Condition cCreateLambdaLogGroup
+
+Resources:
+ rCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Condition: cCommonPrerequisitesNotInstalled
+ Properties:
+ Name: !Sub '${pCodeBuildProjectName}'
+ Artifacts:
+ Type: NO_ARTIFACTS
+ Description: "Codebuild project to get SRA code from github"
+ Environment:
+ ComputeType: BUILD_GENERAL1_SMALL
+ EnvironmentVariables:
+ - Name: AWS_DEFAULT_REGION
+ Value: !Ref AWS::Region
+ - Name: AWS_ACCOUNT_ID
+ Value: !Ref "AWS::AccountId"
+ - Name: SRA_STAGING_S3_BUCKET_STACK_NAME
+ Value: !Ref pSRAStagingS3BucketStackName
+ - Name: SRA_REPO_URL
+ Value: !Ref pRepoURL
+ - Name: SRA_REPO_BRANCH_NAME
+ Value: !Ref pRepoBranch
+ Image: "aws/codebuild/standard:5.0"
+ PrivilegedMode: true
+ Type: "LINUX_CONTAINER"
+ ServiceRole: !GetAtt rCodeBuildRole.Arn
+ TimeoutInMinutes: 120
+ Source:
+ Type: NO_SOURCE
+ BuildSpec: !Sub |
+ version: 0.2
+ phases:
+ pre_build:
+ commands:
+ - echo Build started on `date`...
+ build:
+ commands:
+ - echo Build started on `date` in ${AWS::Region} region
+ - echo Cloning SRA code repository from $SRA_REPO_URL...
+ - git clone $SRA_REPO_URL
+ - echo Listing current directory...
+ - ls
+ - cd aws-security-reference-architecture-examples
+ - git checkout $SRA_REPO_BRANCH_NAME
+ - echo Showing current caller identity...
+ - aws sts get-caller-identity
+ - echo Deploying SRA staging bucket cloudformation template...
+ - aws cloudformation deploy --template-file ./aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml --stack-name $SRA_STAGING_S3_BUCKET_STACK_NAME --capabilities CAPABILITY_NAMED_IAM
+ - echo Staging SRA solutions...
+ - ./aws_sra_examples/utils/packaging_scripts/stage_solution.sh
+ post_build:
+ commands:
+ - echo Build completed on `date`
+
+ rCommonPrerequisitesManagementAccountParametersStack:
+ Type: AWS::CloudFormation::Stack
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rStartCodeBuildProjectCustomResource
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub
+ - https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-management-account-parameters.yaml
+ - SRAStagingS3BucketName: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ Tags:
+ - Key: sra-solution
+ Value: !Ref pSRASolutionName
+ Parameters:
+ pControlTower: !Ref pControlTower
+ pGovernedRegions: !Ref pGovernedRegions
+ pSecurityAccountId: !Ref pSecurityAccountId
+ pLogArchiveAccountId: !Ref pLogArchiveAccountId
+
+ rCommonPrerequisitesMainSsm:
+ Type: AWS::CloudFormation::Stack
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCommonPrerequisitesManagementAccountParametersStack
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub
+ - https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-main-ssm.yaml
+ - SRAStagingS3BucketName: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ Tags:
+ - Key: sra-solution
+ Value: !Ref pSRASolutionName
+ Parameters:
+ pCreateAWSControlTowerExecutionRole: !Ref pCreateAWSControlTowerExecutionRole
+ pControlTower: !Ref pControlTower
+
+ rCodeBuildRole:
+ Type: AWS::IAM::Role
+ Condition: cCommonPrerequisitesNotInstalled
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ - id: W11
+ reason: Allow * in resource when required
+ - id: W28
+ reason: The role name is defined to identify automation resources
+ Properties:
+ RoleName: !Sub '${pCodeBuildRoleName}'
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - codebuild.amazonaws.com
+ Action:
+ - "sts:AssumeRole"
+ Policies:
+ - PolicyName: "logs-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"
+ - PolicyName: "cloudformation-changeset-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:CreateChangeSet
+ - cloudformation:DescribeChangeSet
+ - cloudformation:ExecuteChangeSet
+ - cloudformation:GetTemplateSummary
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*"
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:changeSet/*"
+ - PolicyName: "cloudformation-describe-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:DescribeStacks
+ Resource: "*"
+ - PolicyName: "IAM-Access-Policy"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - iam:GetRole
+ - iam:PassRole
+ - iam:GetRolePolicy
+ - iam:PutRolePolicy
+ - iam:CreateRole
+ - iam:DeleteRolePolicy
+ - iam:DeleteRole
+ - iam:TagRole
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/sra*"
+ - PolicyName: "lambda-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - lambda:GetFunction
+ - lambda:GetFunctionCodeSigningConfig
+ - lambda:GetRuntimeManagementConfig
+ - lambda:CreateFunction
+ - lambda:DeleteFunction
+ - lambda:TagResource
+ - lambda:InvokeFunction
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:sra*"
+ - PolicyName: "s3-staging-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ - s3:ListBucket
+ - s3:GetBucketAcl
+ - s3:GetBucketPolicy
+ - s3:DeleteBucket
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
+ - PolicyName: "s3-create-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:PutBucketPolicy
+ - s3:PutBucketTagging
+ - s3:PutBucketPublicAccessBlock
+ - s3:GetEncryptionConfiguration
+ - s3:PutEncryptionConfiguration
+ - s3:PutBucketOwnershipControls
+ - s3:CreateBucket
+ - s3:PutBucketAcl
+ - s3:PutBucketObjectLockConfiguration
+ - s3:PutBucketVersioning
+ - s3:SetBucketEncryption
+ - s3:PutBucketEncryption
+ Resource:
+ - "arn:aws:s3:::*"
+ - PolicyName: "ssm-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - ssm:GetParameter
+ - ssm:GetParameters
+ - ssm:PutParameter
+ - ssm:AddTagsToResource
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/sra*"
+
+ rStartCodeBuildProjectCustomResource:
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCodeBuildProject
+ Type: Custom::LambdaCustomResource
+ Version: '1.0'
+ Properties:
+ ServiceToken: !GetAtt rStartCodeBuildProjectLambdaFunction.Arn
+
+ rStartCodeBuildProjectLambdaFunction:
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ - id: W58
+ reason: Lambda role provides access to CloudWatch Logs
+ - id: W89
+ reason: Lambda does not need to communicate with VPC resources.
+ - id: W92
+ reason: Lambda does not need reserved concurrent executions.
+ checkov:
+ skip:
+ - id: CKV_AWS_115
+ comment: Lambda does not need reserved concurrent executions.
+ - id: CKV_AWS_116
+ comment: DLQ not needed, as Lambda function only triggered by CloudFormation events.
+ - id: CKV_AWS_117
+ comment: Lambda does not need to communicate with VPC resources.
+ - id: CKV_AWS_173
+ comment: Environment variables are not sensitive.
+ Type: AWS::Lambda::Function
+ Condition: cCommonPrerequisitesNotInstalled
+ Properties:
+ FunctionName: !Ref pCodeBuildProjectLambdaFunctionName
+ Description: Start SRA codebuild project
+ Architectures: !If
+ - cUseGraviton
+ - [arm64]
+ - !Ref AWS::NoValue
+ Handler: index.lambda_handler
+ Role: !GetAtt rStartCodeBuildProjectLambdaRole.Arn
+ Runtime: python3.9
+ Timeout: 900
+ Environment:
+ Variables:
+ LOG_LEVEL: !Ref pLambdaLogLevel
+ CODE_BUILD_PROJECT_NAME: !Ref pCodeBuildProjectName
+ SRA_STAGING_S3_BUCKET_NAME: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ SRA_STAGING_S3_BUCKET_STACK_NAME: !Ref pSRAStagingS3BucketStackName
+ SRA_CUSTOM_RESOURCE_NAME: !Sub ${pCodeBuildProjectLambdaFunctionName}-Custom-Resource
+ Tags:
+ - Key: !Ref pSRASolutionTagKey
+ Value: !Ref pSRASolutionName
+ Code:
+ ZipFile: |
+ # type: ignore
+ """Custom Resource to start codebuild project.
+
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: MIT-0
+ """
+ import logging
+ import os
+
+ import boto3
+ import cfnresponse
+ import time
+ from botocore.exceptions import ClientError
+
+ LOGGER = logging.getLogger(__name__)
+ log_level: str = os.environ.get("LOG_LEVEL", "INFO")
+ LOGGER.setLevel(log_level)
+ CODE_BUILD_PROJECT_NAME: str = os.environ.get("CODE_BUILD_PROJECT_NAME")
+ SRA_CUSTOM_RESOURCE_NAME: str = os.environ.get("SRA_CUSTOM_RESOURCE_NAME")
+
+
+ def start_build():
+ management_account_session = boto3.Session()
+ codebuild_client = management_account_session.client("codebuild")
+ response = codebuild_client.start_build(projectName=CODE_BUILD_PROJECT_NAME)
+ LOGGER.info({"API_Call": "codebuild:StartBuild", "API_Response": response})
+ buildId = response["build"]["id"]
+ return wait_for_build([buildId], codebuild_client)
+
+
+ def wait_for_build(BuildId, client):
+ buildWaitStatus = "FAILURE_WAIT_TIMEOUT"
+ counter = 0
+ while counter < 60:
+ time.sleep(10)
+ counter = counter + 1
+ buildStatus = get_build_status(BuildId, client)
+ if buildStatus == "SUCCEEDED":
+ buildWaitStatus = "SUCCESS"
+ break
+ elif buildStatus == "FAILED" or buildStatus == "FAULT" or buildStatus == "STOPPED" or buildStatus == "TIMED_OUT":
+ buildWaitStatus = "BUILD " + buildStatus + " (check codebuild project cloudwatch log group for details)"
+ break
+ return buildWaitStatus
+
+
+ def get_build_status(buildId, client):
+ build = client.batch_get_builds(ids=buildId)
+ return build["builds"][0]["buildStatus"]
+
+
+ def create_event(event, context):
+ try:
+ data = {"data": start_build()}
+ if data["data"] == "SUCCESS":
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, data, SRA_CUSTOM_RESOURCE_NAME)
+ else:
+ reason = f"See the details in CloudWatch Log Stream: '{context.log_group_name} and CloudFormation Events'"
+ cfnresponse.send(event, context, cfnresponse.FAILED, data, SRA_CUSTOM_RESOURCE_NAME)
+ except Exception:
+ LOGGER.exception("Unexpected!")
+ reason = f"See the details in CloudWatch Log Stream: '{context.log_group_name}'"
+ cfnresponse.send(event, context, cfnresponse.FAILED, {}, SRA_CUSTOM_RESOURCE_NAME, reason=reason)
+ return SRA_CUSTOM_RESOURCE_NAME
+
+
+ def delete_event(event, context):
+ LOGGER.info("entered delete_event function. Nothing to do...")
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, {"delete_operation": "succeeded deleting"}, SRA_CUSTOM_RESOURCE_NAME)
+
+
+ def lambda_handler(event, context):
+ LOGGER.info(event)
+ if event["RequestType"] == "Create":
+ LOGGER.info("CREATE EVENT!!")
+ create_event(event, context)
+ if event["RequestType"] == "Update":
+ LOGGER.info("UPDATE EVENT!!")
+
+ if event["RequestType"] == "Delete":
+ LOGGER.info("DELETE EVENT!!")
+ delete_event(event, context)
+
+ rStartCodeBuildProjectLambdaLogGroup:
+ DeletionPolicy: Retain
+ Type: AWS::Logs::LogGroup
+ Condition: cCommonPrerequisitesNotInstalled
+ UpdateReplacePolicy: Retain
+ Properties:
+ LogGroupName: !Sub /aws/lambda/${pCodeBuildProjectLambdaFunctionName}
+ KmsKeyId: !If
+ - cUsingKmsKey
+ - !Ref pLambdaLogGroupKmsKey
+ - !Ref AWS::NoValue
+ RetentionInDays: !Ref pLambdaLogGroupRetention
+
+ rStartCodeBuildProjectLambdaRole:
+ Type: AWS::IAM::Role
+ Condition: cCommonPrerequisitesNotInstalled
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ # - id: W11
+ # reason: Allow * in resource when required
+ - id: W28
+ reason: The role name is defined to identify automation resources
+ Properties:
+ RoleName: !Ref pCodeBuildProjectLambdaRoleName
+ Description: !Sub Role for '${pCodeBuildProjectLambdaRoleName}' Lambda function
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action: sts:AssumeRole
+ Principal:
+ Service:
+ - lambda.amazonaws.com
+ Tags:
+ - Key: !Ref pSRASolutionTagKey
+ Value: !Ref pSRASolutionName
+ Policies:
+ - PolicyName: codebuild-access
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Sid: codebuildStartBuild
+ Effect: Allow
+ Action:
+ - codebuild:StartBuild
+ - codebuild:BatchGetBuilds
+ Resource: !GetAtt rCodeBuildProject.Arn
+ - PolicyName: CloudWatchLogGroup-access
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Sid: CloudWatchLogs
+ Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pCodeBuildProjectLambdaFunctionName}:log-stream:*
+ - PolicyName: "s3-staging-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ - s3:ListBucket
+ - s3:GetBucketAcl
+ - s3:GetBucketPolicy
+ - s3:GetObjectAcl
+ - s3:PutObjectAcl
+ - s3:DeleteBucket
+ - s3:DeleteObject
+ - s3:DeleteObjectVersion
+ - s3:GetBucketVersioning
+ - s3:DeleteBucketPolicy
+ - s3:ListBucketVersions
+ - s3:PutBucketVersioning
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
+ - PolicyName: "lambda-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - lambda:DeleteFunction
+ - lambda:InvokeFunction
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:sra*"
+ - PolicyName: "cloudformation-stack-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:DeleteStack
+ - cloudformation:DescribeStacks
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/sra*"
+ - PolicyName: "IAM-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - iam:DeleteRole
+ - iam:DeleteRolePolicy
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/sra*"
+
+
+ rCloudTrailSolutionStack:
+ Type: AWS::CloudFormation::Stack
+ DependsOn: WaitCondition
+ Condition: cDeployCloudTrailSolution
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub https://${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}.s3.${AWS::Region}.${AWS::URLSuffix}/sra-cloudtrail-org/templates/sra-cloudtrail-org-main-ssm.yaml
+ Parameters:
+ pBucketNamePrefix: !Ref pBucketNamePrefix
+ pCloudTrailLogGroupKmsKey: !Ref pCloudTrailLogGroupKmsKey
+ pCloudTrailLogGroupRetention: !Ref pCloudTrailLogGroupRetention
+ pCloudTrailName: !Ref pCloudTrailName
+ pCreateCloudTrailLogGroup: !Ref pCreateCloudTrailLogGroup
+ pCreateLambdaLogGroup: !If [cCreateLambdaLogGroup, true, false]
+ pEnableDataEventsOnly: !Ref pEnableDataEventsOnly
+ pEnableLambdaDataEvents: !Ref pEnableLambdaDataEvents
+ pEnableS3DataEvents: !Ref pEnableS3DataEvents
+ pLambdaLogGroupKmsKey: !Ref pLambdaLogGroupKmsKey
+ pLambdaLogGroupRetention: !Ref pLambdaLogGroupRetention
+ pLambdaLogLevel: !Ref pLambdaLogLevel
+ pOrganizationCloudTrailKeyAlias: !Ref pOrganizationCloudTrailKeyAlias
+
+
+ CommonPrerequisitesMainSsmWaitHandle:
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCommonPrerequisitesMainSsm
+ Type: "AWS::CloudFormation::WaitConditionHandle"
+
+ WaitHandle:
+ Type: "AWS::CloudFormation::WaitConditionHandle"
+
+ WaitCondition:
+ Type: "AWS::CloudFormation::WaitCondition"
+ Properties:
+ Handle: !If [cCommonPrerequisitesNotInstalled, !Ref CommonPrerequisitesMainSsmWaitHandle, !Ref WaitHandle]
+ Timeout: "1"
+ Count: 0
+
+Outputs:
+ oAuditAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Audit Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oAuditAccountId]
+ oCustomerControlTowerRegions:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Customer Control Tower Regions
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oCustomerControlTowerRegions]
+ oEnabledRegions:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Enabled Regions
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oEnabledRegions]
+ oEnabledRegionsWithoutHomeRegion:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Enabled Regions without Home Region
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oEnabledRegionsWithoutHomeRegion]
+ oHomeRegion:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Control Tower Home Region
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oHomeRegion]
+ oLogArchiveAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Log Archive Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oLogArchiveAccountId]
+ oManagementAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountId]
+ oRootOrganizationalUnitId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Root Organizational Unit ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oRootOrganizationalUnitId]
+ oManagementAccountParametersLambdaFunctionArn:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account Parameters Lambda Function ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaFunctionArn]
+ oManagementAccountParametersLambdaLogGroupArn:
+ Condition: cLambdaLogGrouOutput
+ Description: Management Account Parameters Lambda Log Group ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaLogGroupArn]
+ oManagementAccountParametersLambdaRoleArn:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account Parameters Lambda Role ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaRoleArn]
+
+ oOrganizationCloudTrailS3BucketName:
+ Condition: cDeployCloudTrailSolution
+ Description: Organization CloudTrail S3 Bucket Name
+ Value: !GetAtt [rCloudTrailSolutionStack, Outputs.oOrganizationCloudTrailS3BucketName]
+ oOrganizationCloudTrailS3BucketArn:
+ Condition: cDeployCloudTrailSolution
+ Description: Organization CloudTrail S3 Bucket Arn
+ Value: !GetAtt [rCloudTrailSolutionStack, Outputs.oOrganizationCloudTrailS3BucketArn]
diff --git a/aws_sra_examples/modules/guardduty-org-module/templates/sra-guardduty-org-module-main.yaml b/aws_sra_examples/modules/guardduty-org-module/templates/sra-guardduty-org-module-main.yaml
new file mode 100644
index 00000000..b2cf5b3a
--- /dev/null
+++ b/aws_sra_examples/modules/guardduty-org-module/templates/sra-guardduty-org-module-main.yaml
@@ -0,0 +1,1207 @@
+########################################################################
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: MIT-0
+########################################################################
+AWSTemplateFormatVersion: '2010-09-09'
+Description: Installs the AWS SRA GuardDuty solution. If needed, the AWS SRA common prerequisite solution is also installed. (sra-1u3sd7f8m)
+Metadata:
+ SRA:
+ Version: 1.0
+ Order: 1
+ AWS::CloudFormation::Interface:
+ ParameterGroups:
+ - Label:
+ default: General Properties
+ Parameters:
+ - pSRASolutionName
+ - pSRAHelperBucketNamePrefix
+ - pRandomParameter
+ - pDisableGuardDuty
+ - pSRAAlarmEmail
+ - Label:
+ default: Landing Zone
+ Parameters:
+ - pControlTower
+ - pGovernedRegions
+ - pSecurityAccountId
+ - pLogArchiveAccountId
+ - pCreateAWSControlTowerExecutionRole
+ - Label:
+ default: SRA Code Repo
+ Parameters:
+ - pRepoURL
+ - pRepoBranch
+ - pTemplateURL
+ - Label:
+ default: CodeBuild
+ Parameters:
+ - pCodeBuildProjectName
+ - pCodeBuildProjectLambdaFunctionName
+ - pCodeBuildRoleName
+ - pCodeBuildProjectLambdaRoleName
+ - Label:
+ default: Lambda
+ Parameters:
+ - pCreateLambdaLogGroup
+ - pLambdaLogGroupKmsKey
+ - pLambdaLogGroupRetention
+ - pLambdaLogLevel
+ - pCheckForResourceLambdaFunctionName
+ - pGetCommonOutputsLambdaFunctionName
+ - pCheckForResourceLambdaRoleName
+ - Label:
+ default: GuardDuty
+ Parameters:
+ - pDisableGuardDuty
+ - pAutoEnableS3Logs
+ - pAutoEnableKubernetesAuditLogs
+ - pAutoEnableMalwareProtection
+ - pEnableRdsLoginEvents
+ - pEnableEksRuntimeMonitoring
+ - pEnableEksAddonManagement
+ - pEnableLambdaNetworkLogs
+ - pGuardDutyFindingPublishingFrequency
+ - pGuardDutyOrgDeliveryBucketPrefix
+ - pGuardDutyOrgDeliveryKeyAlias
+
+ ParameterLabels:
+ pSRASolutionName:
+ default: pSRASolutionName
+ pSRAHelperBucketNamePrefix:
+ default: pSRAHelperBucketNamePrefix
+ pRandomParameter:
+ default: pRandomParameter
+ pSRAAlarmEmail:
+ default: pSRAAlarmEmail
+ pControlTower:
+ default: pControlTower
+ pGovernedRegions:
+ default: pGovernedRegions
+ pSecurityAccountId:
+ default: pSecurityAccountId
+ pLogArchiveAccountId:
+ default: pLogArchiveAccountId
+ pRepoURL:
+ default: pRepoURL
+ pRepoBranch:
+ default: pRepoBranch
+ pTemplateURL:
+ default: pTemplateURL
+ pCodeBuildProjectName:
+ default: pCodeBuildProjectName
+ pCodeBuildProjectLambdaFunctionName:
+ default: pCodeBuildProjectLambdaFunctionName
+ pCodeBuildRoleName:
+ default: pCodeBuildRoleName
+ pCodeBuildProjectLambdaRoleName:
+ default: pCodeBuildProjectLambdaRoleName
+ pCreateLambdaLogGroup:
+ default: pCreateLambdaLogGroup
+ pLambdaLogGroupKmsKey:
+ default: pLambdaLogGroupKmsKey
+ pLambdaLogGroupRetention:
+ default: pLambdaLogGroupRetention
+ pLambdaLogLevel:
+ default: pLambdaLogLevel
+ pCheckForResourceLambdaFunctionName:
+ default: pCheckForResourceLambdaFunctionName
+ pGetCommonOutputsLambdaFunctionName:
+ default: pGetCommonOutputsLambdaFunctionName
+ pCheckForResourceLambdaRoleName:
+ default: pCheckForResourceLambdaRoleName
+ pDisableGuardDuty:
+ default: pDisableGuardDuty
+ pAutoEnableS3Logs:
+ default: pAutoEnableS3Logs
+ pAutoEnableKubernetesAuditLogs:
+ default: pAutoEnableKubernetesAuditLogs
+ pAutoEnableMalwareProtection:
+ default: pAutoEnableMalwareProtection
+ pEnableRdsLoginEvents:
+ default: pEnableRdsLoginEvents
+ pEnableEksRuntimeMonitoring:
+ default: pEnableEksRuntimeMonitoring
+ pEnableEksAddonManagement:
+ default: pEnableEksAddonManagement
+ pEnableLambdaNetworkLogs:
+ default: pEnableLambdaNetworkLogs
+ pGuardDutyFindingPublishingFrequency:
+ default: pGuardDutyFindingPublishingFrequency
+ pGuardDutyOrgDeliveryBucketPrefix:
+ default: pGuardDutyOrgDeliveryBucketPrefix
+ pGuardDutyOrgDeliveryKeyAlias:
+ default: pGuardDutyOrgDeliveryKeyAlias
+ pCreateAWSControlTowerExecutionRole:
+ default: Create AWS Control Tower Execution Role
+
+Parameters:
+ pSRAHelperBucketNamePrefix:
+ AllowedValues: [sra-helper]
+ Default: sra-helper
+ Description:
+ SRA helper S3 bucket name prefix
+ Type: String
+ pCodeBuildProjectName:
+ AllowedValues: [sra-helper-guardduty-codebuild-project]
+ Default: sra-helper-guardduty-codebuild-project
+ Description:
+ SRA CodeBuild project name
+ Type: String
+ pTemplateURL:
+ Default: https://raw.githubusercontent.com/aws-samples/aws-security-reference-architecture-examples/v3.0.4/aws_sra_examples/modules/guardduty-org-module/templates/sra-guardduty-org-solution.yaml
+ Description:
+ SRA module solution template URL
+ Type: String
+ pRepoURL:
+ Default: https://github.com/aws-samples/aws-security-reference-architecture-examples.git
+ Description:
+ SRA Code Library Repository URL
+ Type: String
+ pRepoBranch:
+ Default: tags/v3.0.4
+ Description:
+ SRA Code Library Repository branch name. Can be used as branch or as tags (e.g. tags/v3.0.1)
+ Type: String
+
+ pControlTower:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description:
+ Indicates whether AWS Control Tower is deployed and being used for this AWS environment.
+ Type: String
+ pGovernedRegions:
+ AllowedPattern: '^(ct-regions)|((\b(?--. Example = sra-staging-123456789012-us-east-1.
+ Type: String
+ pSRAStagingS3BucketStackName:
+ AllowedValues: [sra-common-prerequisites-staging-s3-bucket]
+ Default: sra-common-prerequisites-staging-s3-bucket
+ Description:
+ SRA Common Prerequisite Staging S3 bucket stack name. This stack will be created by the SRA CodeBuild Project.
+ Type: String
+
+ pCreateLambdaLogGroup:
+ AllowedValues: ['Yes', 'No']
+ Default: 'No'
+ Description:
+ Indicates whether a CloudWatch Log Group should be explicitly created for the Lambda function, to allow for setting a Log Retention and/or KMS
+ Key for encryption.
+ Type: String
+
+ pLambdaLogGroupKmsKey:
+ AllowedPattern: '^$|^arn:(aws[a-zA-Z-]*){1}:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'
+ ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
+ Default: ''
+ Description:
+ (Optional) KMS Key ARN to use for encrypting the Lambda logs data. If empty, encryption is enabled with CloudWatch Logs managing the server-side
+ encryption keys.
+ Type: String
+ pLambdaLogGroupRetention:
+ AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
+ Default: 14
+ Description: Specifies the number of days you want to retain log events
+ Type: String
+ pLambdaLogLevel:
+ AllowedValues: [INFO, ERROR, DEBUG]
+ Default: INFO
+ Description: Lambda Function Logging Level
+ Type: String
+
+ pSRAAlarmEmail:
+ AllowedPattern: '^$|^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)$'
+ ConstraintDescription: Must be a valid email address.
+ Default: ''
+ Description: (Optional) Email address for receiving SRA alarms
+ Type: String
+ pCreateAWSControlTowerExecutionRole:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Indicates whether the AWS Control Tower Execution role should be created.
+ Type: String
+
+ pDeployGuardDutySolution:
+ AllowedValues: ['Yes', 'No']
+ Default: 'Yes'
+ Description: Deploy the GuardDuty solution
+ Type: String
+ pDisableGuardDuty:
+ AllowedValues: ['Yes', 'No']
+ Default: 'No'
+ Description: Disable the GuardDuty solution in all accounts and regions before deleting the stack.
+ Type: String
+ pAutoEnableS3Logs:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable S3 logs
+ Type: String
+ pAutoEnableKubernetesAuditLogs:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable Kubernetes Audit Logs
+ Type: String
+ pAutoEnableMalwareProtection:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable Malware Protection
+ Type: String
+ pEnableRdsLoginEvents:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable RDS Login Events
+ Type: String
+ pEnableEksRuntimeMonitoring:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable EKS Runtime Monitoring
+ Type: String
+ pEnableEksAddonManagement:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable EKS Add-on Management
+ Type: String
+ pEnableLambdaNetworkLogs:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Auto enable Lambda Network Logs
+ Type: String
+ pGuardDutyFindingPublishingFrequency:
+ AllowedValues: [FIFTEEN_MINUTES, ONE_HOUR, SIX_HOURS]
+ Default: FIFTEEN_MINUTES
+ Description: Finding publishing frequency
+ Type: String
+ pGuardDutyOrgDeliveryBucketPrefix:
+ AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$'
+ ConstraintDescription:
+ S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
+ Default: sra-guardduty-org-delivery
+ Description:
+ GuardDuty Delivery S3 bucket prefix. The account and region will get added to the end. e.g. sra-guardduty-delivery-123456789012-us-east-1
+ Type: String
+ pGuardDutyOrgDeliveryKeyAlias:
+ Default: sra-guardduty-org-delivery-key
+ Description: GuardDuty Delivery KMS Key Alias
+ Type: String
+
+# Rules:
+
+Conditions:
+ cUsingKmsKey: !Not [!Equals [!Ref pLambdaLogGroupKmsKey, '']]
+ cUseGraviton: !Or
+ - !Equals [!Ref 'AWS::Region', ap-northeast-1]
+ - !Equals [!Ref 'AWS::Region', ap-south-1]
+ - !Equals [!Ref 'AWS::Region', ap-southeast-1]
+ - !Equals [!Ref 'AWS::Region', ap-southeast-2]
+ - !Equals [!Ref 'AWS::Region', eu-central-1]
+ - !Equals [!Ref 'AWS::Region', eu-west-1]
+ - !Equals [!Ref 'AWS::Region', eu-west-2]
+ - !Equals [!Ref 'AWS::Region', us-east-1]
+ - !Equals [!Ref 'AWS::Region', us-east-2]
+ - !Equals [!Ref 'AWS::Region', us-west-2]
+
+ cCommonPrerequisitesNotInstalled: !Equals [!Ref pCommonPrerequisitesInstalled, 'false']
+ cCreateLambdaLogGroup: !Equals [!Ref pCreateLambdaLogGroup, 'Yes']
+ cDeployGuardDutySolution: !Equals [!Ref pDeployGuardDutySolution, 'Yes']
+ cDisableGuardDuty: !Equals [!Ref pDisableGuardDuty, 'Yes']
+ cCreateLogGroupAndCommonPrereqInstalled: !And
+ - !Condition cCreateLambdaLogGroup
+ - !Condition cCommonPrerequisitesNotInstalled
+
+
+Resources:
+ rCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Condition: cCommonPrerequisitesNotInstalled
+ Properties:
+ Name: !Sub '${pCodeBuildProjectName}'
+ Artifacts:
+ Type: NO_ARTIFACTS
+ Description: "Codebuild project to get SRA code from github"
+ Environment:
+ ComputeType: BUILD_GENERAL1_SMALL
+ EnvironmentVariables:
+ - Name: AWS_DEFAULT_REGION
+ Value: !Ref AWS::Region
+ - Name: AWS_ACCOUNT_ID
+ Value: !Ref "AWS::AccountId"
+ - Name: SRA_STAGING_S3_BUCKET_STACK_NAME
+ Value: !Ref pSRAStagingS3BucketStackName
+ - Name: SRA_REPO_URL
+ Value: !Ref pRepoURL
+ - Name: SRA_REPO_BRANCH_NAME
+ Value: !Ref pRepoBranch
+ Image: "aws/codebuild/standard:5.0"
+ PrivilegedMode: true
+ Type: "LINUX_CONTAINER"
+ ServiceRole: !GetAtt rCodeBuildRole.Arn
+ TimeoutInMinutes: 120
+ Source:
+ Type: NO_SOURCE
+ BuildSpec: !Sub |
+ version: 0.2
+ phases:
+ pre_build:
+ commands:
+ - echo Build started on `date`...
+ build:
+ commands:
+ - echo Build started on `date` in ${AWS::Region} region
+ - echo Cloning SRA code repository from $SRA_REPO_URL...
+ - git clone $SRA_REPO_URL
+ - echo Listing current directory...
+ - ls
+ - cd aws-security-reference-architecture-examples
+ - git checkout $SRA_REPO_BRANCH_NAME
+ - echo Showing current caller identity...
+ - aws sts get-caller-identity
+ - echo Deploying SRA staging bucket cloudformation template...
+ - aws cloudformation deploy --template-file ./aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml --stack-name $SRA_STAGING_S3_BUCKET_STACK_NAME --capabilities CAPABILITY_NAMED_IAM
+ - echo Staging SRA solutions...
+ - ./aws_sra_examples/utils/packaging_scripts/stage_solution.sh
+ post_build:
+ commands:
+ - echo Build completed on `date`
+
+ rCommonPrerequisitesManagementAccountParametersStack:
+ Type: AWS::CloudFormation::Stack
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rStartCodeBuildProjectCustomResource
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub
+ - https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-management-account-parameters.yaml
+ - SRAStagingS3BucketName: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ Tags:
+ - Key: sra-solution
+ Value: !Ref pSRASolutionName
+ Parameters:
+ pControlTower: !Ref pControlTower
+ pGovernedRegions: !Ref pGovernedRegions
+ pSecurityAccountId: !Ref pSecurityAccountId
+ pLogArchiveAccountId: !Ref pLogArchiveAccountId
+
+ rCommonPrerequisitesMainSsm:
+ Type: AWS::CloudFormation::Stack
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCommonPrerequisitesManagementAccountParametersStack
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub
+ - https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-main-ssm.yaml
+ - SRAStagingS3BucketName: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ Tags:
+ - Key: sra-solution
+ Value: !Ref pSRASolutionName
+ Parameters:
+ pCreateAWSControlTowerExecutionRole: !Ref pCreateAWSControlTowerExecutionRole
+ pControlTower: !Ref pControlTower
+
+ rCodeBuildRole:
+ Type: AWS::IAM::Role
+ Condition: cCommonPrerequisitesNotInstalled
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ - id: W11
+ reason: Allow * in resource when required
+ - id: W28
+ reason: The role name is defined to identify automation resources
+ Properties:
+ RoleName: !Sub '${pCodeBuildRoleName}'
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - codebuild.amazonaws.com
+ Action:
+ - "sts:AssumeRole"
+ Policies:
+ - PolicyName: "logs-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"
+ - PolicyName: "cloudformation-changeset-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:CreateChangeSet
+ - cloudformation:DescribeChangeSet
+ - cloudformation:ExecuteChangeSet
+ - cloudformation:GetTemplateSummary
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*"
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:changeSet/*"
+ - PolicyName: "cloudformation-describe-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:DescribeStacks
+ Resource: "*"
+ - PolicyName: "IAM-Access-Policy"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - iam:GetRole
+ - iam:PassRole
+ - iam:GetRolePolicy
+ - iam:PutRolePolicy
+ - iam:CreateRole
+ - iam:DeleteRolePolicy
+ - iam:DeleteRole
+ - iam:TagRole
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/sra*"
+ - PolicyName: "lambda-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - lambda:GetFunction
+ - lambda:GetFunctionCodeSigningConfig
+ - lambda:GetRuntimeManagementConfig
+ - lambda:CreateFunction
+ - lambda:DeleteFunction
+ - lambda:TagResource
+ - lambda:InvokeFunction
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:sra*"
+ - PolicyName: "s3-staging-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ - s3:ListBucket
+ - s3:GetBucketAcl
+ - s3:GetBucketPolicy
+ - s3:DeleteBucket
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
+ - PolicyName: "s3-create-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:PutBucketPolicy
+ - s3:PutBucketTagging
+ - s3:PutBucketPublicAccessBlock
+ - s3:GetEncryptionConfiguration
+ - s3:PutEncryptionConfiguration
+ - s3:PutBucketOwnershipControls
+ - s3:CreateBucket
+ - s3:PutBucketAcl
+ - s3:PutBucketObjectLockConfiguration
+ - s3:PutBucketVersioning
+ - s3:SetBucketEncryption
+ - s3:PutBucketEncryption
+ Resource:
+ - "arn:aws:s3:::*"
+ - PolicyName: "ssm-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - ssm:GetParameter
+ - ssm:GetParameters
+ - ssm:PutParameter
+ - ssm:AddTagsToResource
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/sra*"
+
+ rStartCodeBuildProjectCustomResource:
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCodeBuildProject
+ Type: Custom::LambdaCustomResource
+ Version: '1.0'
+ Properties:
+ ServiceToken: !GetAtt rStartCodeBuildProjectLambdaFunction.Arn
+
+ rStartCodeBuildProjectLambdaFunction:
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ - id: W58
+ reason: Lambda role provides access to CloudWatch Logs
+ - id: W89
+ reason: Lambda does not need to communicate with VPC resources.
+ - id: W92
+ reason: Lambda does not need reserved concurrent executions.
+ checkov:
+ skip:
+ - id: CKV_AWS_115
+ comment: Lambda does not need reserved concurrent executions.
+ - id: CKV_AWS_116
+ comment: DLQ not needed, as Lambda function only triggered by CloudFormation events.
+ - id: CKV_AWS_117
+ comment: Lambda does not need to communicate with VPC resources.
+ - id: CKV_AWS_173
+ comment: Environment variables are not sensitive.
+ Type: AWS::Lambda::Function
+ Condition: cCommonPrerequisitesNotInstalled
+ Properties:
+ FunctionName: !Ref pCodeBuildProjectLambdaFunctionName
+ Description: Start SRA codebuild project
+ Architectures: !If
+ - cUseGraviton
+ - [arm64]
+ - !Ref AWS::NoValue
+ Handler: index.lambda_handler
+ Role: !GetAtt rStartCodeBuildProjectLambdaRole.Arn
+ Runtime: python3.9
+ Timeout: 900
+ Environment:
+ Variables:
+ LOG_LEVEL: !Ref pLambdaLogLevel
+ CODE_BUILD_PROJECT_NAME: !Ref pCodeBuildProjectName
+ SRA_STAGING_S3_BUCKET_NAME: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ SRA_STAGING_S3_BUCKET_STACK_NAME: !Ref pSRAStagingS3BucketStackName
+ SRA_CUSTOM_RESOURCE_NAME: !Sub ${pCodeBuildProjectLambdaFunctionName}-Custom-Resource
+ Tags:
+ - Key: !Ref pSRASolutionTagKey
+ Value: !Ref pSRASolutionName
+ Code:
+ ZipFile: |
+ # type: ignore
+ """Custom Resource to start codebuild project.
+
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: MIT-0
+ """
+ import logging
+ import os
+
+ import boto3
+ import cfnresponse
+ import time
+ from botocore.exceptions import ClientError
+
+ LOGGER = logging.getLogger(__name__)
+ log_level: str = os.environ.get("LOG_LEVEL", "INFO")
+ LOGGER.setLevel(log_level)
+ CODE_BUILD_PROJECT_NAME: str = os.environ.get("CODE_BUILD_PROJECT_NAME")
+ SRA_CUSTOM_RESOURCE_NAME: str = os.environ.get("SRA_CUSTOM_RESOURCE_NAME")
+
+
+ def start_build():
+ management_account_session = boto3.Session()
+ codebuild_client = management_account_session.client("codebuild")
+ response = codebuild_client.start_build(projectName=CODE_BUILD_PROJECT_NAME)
+ LOGGER.info({"API_Call": "codebuild:StartBuild", "API_Response": response})
+ buildId = response["build"]["id"]
+ return wait_for_build([buildId], codebuild_client)
+
+
+ def wait_for_build(BuildId, client):
+ buildWaitStatus = "FAILURE_WAIT_TIMEOUT"
+ counter = 0
+ while counter < 60:
+ time.sleep(10)
+ counter = counter + 1
+ buildStatus = get_build_status(BuildId, client)
+ if buildStatus == "SUCCEEDED":
+ buildWaitStatus = "SUCCESS"
+ break
+ elif buildStatus == "FAILED" or buildStatus == "FAULT" or buildStatus == "STOPPED" or buildStatus == "TIMED_OUT":
+ buildWaitStatus = "BUILD " + buildStatus + " (check codebuild project cloudwatch log group for details)"
+ break
+ return buildWaitStatus
+
+
+ def get_build_status(buildId, client):
+ build = client.batch_get_builds(ids=buildId)
+ return build["builds"][0]["buildStatus"]
+
+
+ def create_event(event, context):
+ try:
+ data = {"data": start_build()}
+ if data["data"] == "SUCCESS":
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, data, SRA_CUSTOM_RESOURCE_NAME)
+ else:
+ reason = f"See the details in CloudWatch Log Stream: '{context.log_group_name} and CloudFormation Events'"
+ cfnresponse.send(event, context, cfnresponse.FAILED, data, SRA_CUSTOM_RESOURCE_NAME)
+ except Exception:
+ LOGGER.exception("Unexpected!")
+ reason = f"See the details in CloudWatch Log Stream: '{context.log_group_name}'"
+ cfnresponse.send(event, context, cfnresponse.FAILED, {}, SRA_CUSTOM_RESOURCE_NAME, reason=reason)
+ return SRA_CUSTOM_RESOURCE_NAME
+
+
+ def delete_event(event, context):
+ LOGGER.info("entered delete_event function. Nothing to do...")
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, {"delete_operation": "succeeded deleting"}, SRA_CUSTOM_RESOURCE_NAME)
+
+
+ def lambda_handler(event, context):
+ LOGGER.info(event)
+ if event["RequestType"] == "Create":
+ LOGGER.info("CREATE EVENT!!")
+ create_event(event, context)
+ if event["RequestType"] == "Update":
+ LOGGER.info("UPDATE EVENT!!")
+
+ if event["RequestType"] == "Delete":
+ LOGGER.info("DELETE EVENT!!")
+ delete_event(event, context)
+
+ rStartCodeBuildProjectLambdaLogGroup:
+ DeletionPolicy: Retain
+ Type: AWS::Logs::LogGroup
+ Condition: cCommonPrerequisitesNotInstalled
+ UpdateReplacePolicy: Retain
+ Properties:
+ LogGroupName: !Sub /aws/lambda/${pCodeBuildProjectLambdaFunctionName}
+ KmsKeyId: !If
+ - cUsingKmsKey
+ - !Ref pLambdaLogGroupKmsKey
+ - !Ref AWS::NoValue
+ RetentionInDays: !Ref pLambdaLogGroupRetention
+
+ rStartCodeBuildProjectLambdaRole:
+ Type: AWS::IAM::Role
+ Condition: cCommonPrerequisitesNotInstalled
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ # - id: W11
+ # reason: Allow * in resource when required
+ - id: W28
+ reason: The role name is defined to identify automation resources
+ Properties:
+ RoleName: !Ref pCodeBuildProjectLambdaRoleName
+ Description: !Sub Role for '${pCodeBuildProjectLambdaRoleName}' Lambda function
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action: sts:AssumeRole
+ Principal:
+ Service:
+ - lambda.amazonaws.com
+ Tags:
+ - Key: !Ref pSRASolutionTagKey
+ Value: !Ref pSRASolutionName
+ Policies:
+ - PolicyName: codebuild-access
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Sid: codebuildStartBuild
+ Effect: Allow
+ Action:
+ - codebuild:StartBuild
+ - codebuild:BatchGetBuilds
+ Resource: !GetAtt rCodeBuildProject.Arn
+ - PolicyName: CloudWatchLogGroup-access
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Sid: CloudWatchLogs
+ Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pCodeBuildProjectLambdaFunctionName}:log-stream:*
+ - PolicyName: "s3-staging-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ - s3:ListBucket
+ - s3:GetBucketAcl
+ - s3:GetBucketPolicy
+ - s3:GetObjectAcl
+ - s3:PutObjectAcl
+ - s3:DeleteBucket
+ - s3:DeleteObject
+ - s3:DeleteObjectVersion
+ - s3:GetBucketVersioning
+ - s3:DeleteBucketPolicy
+ - s3:ListBucketVersions
+ - s3:PutBucketVersioning
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
+ - PolicyName: "lambda-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - lambda:DeleteFunction
+ - lambda:InvokeFunction
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:sra*"
+ - PolicyName: "cloudformation-stack-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:DeleteStack
+ - cloudformation:DescribeStacks
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/sra*"
+ - PolicyName: "IAM-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - iam:DeleteRole
+ - iam:DeleteRolePolicy
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/sra*"
+
+
+ rGuardDutySolutionStack:
+ Type: AWS::CloudFormation::Stack
+ DependsOn: WaitCondition
+ Condition: cDeployGuardDutySolution
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub https://${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}.s3.${AWS::Region}.${AWS::URLSuffix}/sra-guardduty-org/templates/sra-guardduty-org-main-ssm.yaml
+ Parameters:
+ pAutoEnableS3Logs: !Ref pAutoEnableS3Logs
+ pAutoEnableKubernetesAuditLogs: !Ref pAutoEnableKubernetesAuditLogs
+ pAutoEnableMalwareProtection: !Ref pAutoEnableMalwareProtection
+ pEnableRdsLoginEvents: !Ref pEnableRdsLoginEvents
+ pEnableEksRuntimeMonitoring: !Ref pEnableEksRuntimeMonitoring
+ pEnableEksAddonManagement: !Ref pEnableEksAddonManagement
+ pEnableLambdaNetworkLogs: !Ref pEnableLambdaNetworkLogs
+ pCreateLambdaLogGroup: !If [cCreateLambdaLogGroup, true, false]
+ pDisableGuardDuty: !If [cDisableGuardDuty, true, false]
+ pFindingPublishingFrequency: !Ref pGuardDutyFindingPublishingFrequency
+ pGuardDutyOrgDeliveryBucketPrefix: !Ref pGuardDutyOrgDeliveryBucketPrefix
+ pGuardDutyOrgDeliveryKeyAlias: !Ref pGuardDutyOrgDeliveryKeyAlias
+ pLambdaLogGroupKmsKey: !Ref pLambdaLogGroupKmsKey
+ pLambdaLogGroupRetention: !Ref pLambdaLogGroupRetention
+ pLambdaLogLevel: !Ref pLambdaLogLevel
+ pSRAAlarmEmail: !Ref pSRAAlarmEmail
+
+ CommonPrerequisitesMainSsmWaitHandle:
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCommonPrerequisitesMainSsm
+ Type: "AWS::CloudFormation::WaitConditionHandle"
+
+ WaitHandle:
+ Type: "AWS::CloudFormation::WaitConditionHandle"
+
+ WaitCondition:
+ Type: "AWS::CloudFormation::WaitCondition"
+ Properties:
+ Handle: !If [cCommonPrerequisitesNotInstalled, !Ref CommonPrerequisitesMainSsmWaitHandle, !Ref WaitHandle]
+ Timeout: "1"
+ Count: 0
+
+Outputs:
+ oAuditAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Audit Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oAuditAccountId]
+ oCustomerControlTowerRegions:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Customer Control Tower Regions
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oCustomerControlTowerRegions]
+ oEnabledRegions:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Enabled Regions
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oEnabledRegions]
+ oEnabledRegionsWithoutHomeRegion:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Enabled Regions without Home Region
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oEnabledRegionsWithoutHomeRegion]
+ oHomeRegion:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Control Tower Home Region
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oHomeRegion]
+ oLogArchiveAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Log Archive Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oLogArchiveAccountId]
+ oManagementAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountId]
+ oRootOrganizationalUnitId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Root Organizational Unit ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oRootOrganizationalUnitId]
+ oManagementAccountParametersLambdaFunctionArn:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account Parameters Lambda Function ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaFunctionArn]
+ oManagementAccountParametersLambdaLogGroupArn:
+ Condition: cCreateLogGroupAndCommonPrereqInstalled
+ Description: Management Account Parameters Lambda Log Group ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaLogGroupArn]
+ oManagementAccountParametersLambdaRoleArn:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account Parameters Lambda Role ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaRoleArn]
+
+ oPublishingDestinationBucketName:
+ Condition: cDeployGuardDutySolution
+ Description: Publishing Destination Bucket Name
+ Value: !GetAtt [rGuardDutySolutionStack, Outputs.oPublishingDestinationBucketName]
+ oPublishingDestinationBucketArn:
+ Condition: cDeployGuardDutySolution
+ Description: Publishing Destination Bucket Name
+ Value: !GetAtt [rGuardDutySolutionStack, Outputs.oPublishingDestinationBucketArn]
+ oGuardDutyDeliveryKeyArn:
+ Condition: cDeployGuardDutySolution
+ Description: GuardDuty Delivery KMS Key ARN
+ Value: !GetAtt [rGuardDutySolutionStack, Outputs.oGuardDutyDeliveryKeyArn]
diff --git a/aws_sra_examples/modules/securityhub-org-module/templates/sra-securityhub-org-module-main.yaml b/aws_sra_examples/modules/securityhub-org-module/templates/sra-securityhub-org-module-main.yaml
new file mode 100644
index 00000000..efa9b27f
--- /dev/null
+++ b/aws_sra_examples/modules/securityhub-org-module/templates/sra-securityhub-org-module-main.yaml
@@ -0,0 +1,1173 @@
+########################################################################
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: MIT-0
+########################################################################
+AWSTemplateFormatVersion: '2010-09-09'
+Description: Installs the AWS SRA Security Hub solution. If needed, the AWS SRA common prerequisite solution is also installed. (sra-1u3sd7f90)
+Metadata:
+ SRA:
+ Version: 1.0
+ Order: 1
+ AWS::CloudFormation::Interface:
+ ParameterGroups:
+ - Label:
+ default: General Properties
+ Parameters:
+ - pSRASolutionName
+ - pSRAHelperBucketNamePrefix
+ - pRandomParameter
+ - pComplianceFrequency
+ - pDisableSecurityHub
+ - pRegionLinkingMode
+ - pSRAAlarmEmail
+ - Label:
+ default: Landing Zone
+ Parameters:
+ - pControlTower
+ - pGovernedRegions
+ - pSecurityAccountId
+ - pLogArchiveAccountId
+ - pCreateAWSControlTowerExecutionRole
+ - Label:
+ default: SRA Code Repo
+ Parameters:
+ - pRepoURL
+ - pRepoBranch
+ - pTemplateURL
+ - Label:
+ default: CodeBuild
+ Parameters:
+ - pCodeBuildProjectName
+ - pCodeBuildProjectLambdaFunctionName
+ - pCodeBuildRoleName
+ - pCodeBuildProjectLambdaRoleName
+ - Label:
+ default: Lambda
+ Parameters:
+ - pCreateLambdaLogGroup
+ - pLambdaLogGroupKmsKey
+ - pLambdaLogGroupRetention
+ - pLambdaLogLevel
+ - pCheckForResourceLambdaFunctionName
+ - pGetCommonOutputsLambdaFunctionName
+ - pCheckForResourceLambdaRoleName
+ - Label:
+ default: Standards
+ Parameters:
+ - pCISStandardVersion
+ - pEnableCISStandard
+ - pEnablePCIStandard
+ - pEnableNISTStandard
+ - pNISTStandardVersion
+ - pEnableSecurityBestPracticesStandard
+ ParameterLabels:
+ pSRASolutionName:
+ default: pSRASolutionName
+ pSRAHelperBucketNamePrefix:
+ default: pSRAHelperBucketNamePrefix
+ pRandomParameter:
+ default: pRandomParameter
+ pComplianceFrequency:
+ default: pComplianceFrequency
+ pDisableSecurityHub:
+ default: pDisableSecurityHub
+ pRegionLinkingMode:
+ default: pRegionLinkingMode
+ pSRAAlarmEmail:
+ default: pSRAAlarmEmail
+ pControlTower:
+ default: pControlTower
+ pGovernedRegions:
+ default: pGovernedRegions
+ pSecurityAccountId:
+ default: pSecurityAccountId
+ pLogArchiveAccountId:
+ default: pLogArchiveAccountId
+ pRepoURL:
+ default: pRepoURL
+ pRepoBranch:
+ default: pRepoBranch
+ pTemplateURL:
+ default: pTemplateURL
+ pCodeBuildProjectName:
+ default: pCodeBuildProjectName
+ pCodeBuildProjectLambdaFunctionName:
+ default: pCodeBuildProjectLambdaFunctionName
+ pCodeBuildRoleName:
+ default: pCodeBuildRoleName
+ pCodeBuildProjectLambdaRoleName:
+ default: pCodeBuildProjectLambdaRoleName
+ pCreateLambdaLogGroup:
+ default: pCreateLambdaLogGroup
+ pLambdaLogGroupKmsKey:
+ default: pLambdaLogGroupKmsKey
+ pLambdaLogGroupRetention:
+ default: pLambdaLogGroupRetention
+ pLambdaLogLevel:
+ default: pLambdaLogLevel
+ pCheckForResourceLambdaFunctionName:
+ default: pCheckForResourceLambdaFunctionName
+ pGetCommonOutputsLambdaFunctionName:
+ default: pGetCommonOutputsLambdaFunctionName
+ pCheckForResourceLambdaRoleName:
+ default: pCheckForResourceLambdaRoleName
+ pCISStandardVersion:
+ default: pCISStandardVersion
+ pEnableCISStandard:
+ default: pEnableCISStandard
+ pEnablePCIStandard:
+ default: pEnablePCIStandard
+ pEnableNISTStandard:
+ default: pEnableNISTStandard
+ pNISTStandardVersion:
+ default: pNISTStandardVersion
+ pEnableSecurityBestPracticesStandard:
+ default: pEnableSecurityBestPracticesStandard
+ pCreateAWSControlTowerExecutionRole:
+ default: Create AWS Control Tower Execution Role
+
+
+Parameters:
+ pRepoURL:
+ Default: https://github.com/aws-samples/aws-security-reference-architecture-examples.git
+ Description:
+ SRA Code Library Repository URL
+ Type: String
+ pRepoBranch:
+ Default: tags/v3.0.4
+ Description:
+ SRA Code Library Repository branch name. Can be used as branch or as tags (e.g. tags/v3.0.1)
+ Type: String
+ pTemplateURL:
+ Default: https://raw.githubusercontent.com/aws-samples/aws-security-reference-architecture-examples/v3.0.4/aws_sra_examples/modules/securityhub-org-module/templates/sra-securityhub-org-solution.yaml
+ Description:
+ SRA module solution template URL
+ Type: String
+
+ pControlTower:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description:
+ Indicates whether AWS Control Tower is deployed and being used for this AWS environment.
+ Type: String
+ pGovernedRegions:
+ AllowedPattern: '^(ct-regions)|((\b(?--. Example = sra-staging-123456789012-us-east-1.
+ Type: String
+ pSRAStagingS3BucketStackName:
+ AllowedValues: [sra-common-prerequisites-staging-s3-bucket]
+ Default: sra-common-prerequisites-staging-s3-bucket
+ Description:
+ SRA Common Prerequisite Staging S3 bucket stack name. This stack will be created by the SRA CodeBuild Project.
+ Type: String
+
+ pCISStandardVersion:
+ AllowedValues: [1.2.0, 1.4.0]
+ Default: 1.4.0
+ Description: CIS Standard Version
+ Type: String
+ pComplianceFrequency:
+ ConstraintDescription: Compliance Frequency must be a number between 1 and 30, inclusive.
+ Default: 7
+ Description: Frequency (in days between 1 and 30, default is 7) to check organizational compliance
+ MinValue: 1
+ MaxValue: 30
+ Type: Number
+ pCreateLambdaLogGroup:
+ AllowedValues: ['Yes', 'No']
+ Default: 'No'
+ Description:
+ Indicates whether a CloudWatch Log Group should be explicitly created for the Lambda function, to allow for setting a Log Retention and/or KMS
+ Key for encryption.
+ Type: String
+ pDeployConfigManagementSolution:
+ AllowedValues: ['No', 'Already Deployed']
+ Default: 'Already Deployed'
+ Description: Deploy the AWS Config Management solution. Note, if solution was previously deployed, choose 'Already Deployed'.
+ Type: String
+ pDeploySecurityHubSolution:
+ AllowedValues: ['Yes', 'No']
+ Default: 'Yes'
+ Description: Deploy the Security Hub solution
+ Type: String
+ pDisableSecurityHub:
+ AllowedValues: ['Yes', 'No']
+ Default: 'No'
+ Description: Disable the Security Hub solution in all accounts and regions before deleting the stack.
+ Type: String
+ pEnableCISStandard:
+ AllowedValues: ['true', 'false']
+ Default: 'false'
+ Description: Indicates whether to enable the CIS AWS Foundations Benchmark Standard.
+ Type: String
+ pEnablePCIStandard:
+ AllowedValues: ['true', 'false']
+ Default: 'false'
+ Description: Indicates whether to enable the Payment Card Industry Data Security Standard (PCI DSS).
+ Type: String
+ pEnableSecurityBestPracticesStandard:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Indicates whether to enable the AWS Foundational Security Best Practices Standard.
+ Type: String
+ pLambdaLogGroupKmsKey:
+ AllowedPattern: '^$|^arn:(aws[a-zA-Z-]*){1}:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'
+ ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
+ Default: ''
+ Description:
+ (Optional) KMS Key ARN to use for encrypting the Lambda logs data. If empty, encryption is enabled with CloudWatch Logs managing the server-side
+ encryption keys.
+ Type: String
+ pLambdaLogGroupRetention:
+ AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
+ Default: 14
+ Description: Specifies the number of days you want to retain log events
+ Type: String
+ pLambdaLogLevel:
+ AllowedValues: [INFO, ERROR, DEBUG]
+ Default: INFO
+ Description: Lambda Function Logging Level
+ Type: String
+ pEnableNISTStandard:
+ AllowedValues: ['true', 'false']
+ Default: 'false'
+ Description: Indicates whether to enable the National Institute of Standards and Technology (NIST) SP 800-53 Rev. 5.
+ Type: String
+ pNISTStandardVersion:
+ AllowedValues: [5.0.0]
+ Default: 5.0.0
+ Description: NIST Standard Version
+ Type: String
+ pRegionLinkingMode:
+ AllowedValues: [SPECIFIED_REGIONS, ALL_REGIONS]
+ Default: SPECIFIED_REGIONS
+ Description:
+ Indicates whether to aggregate findings from all of the available Regions in the current partition. Also determines whether to automatically
+ aggregate findings from new Regions as Security Hub supports them and you opt into them.
+ Type: String
+ pSRAAlarmEmail:
+ AllowedPattern: '^$|^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)$'
+ ConstraintDescription: Must be a valid email address.
+ Default: ''
+ Description: (Optional) Email address for receiving SRA alarms
+ Type: String
+ pCreateAWSControlTowerExecutionRole:
+ AllowedValues: ['true', 'false']
+ Default: 'true'
+ Description: Indicates whether the AWS Control Tower Execution role should be created.
+ Type: String
+
+Rules:
+ DeploySecurityHubSolutionValidation:
+ RuleCondition: !Equals [!Ref pDeploySecurityHubSolution, 'Yes']
+ Assertions:
+ - Assert: !Equals [!Ref pDeployConfigManagementSolution, 'Already Deployed']
+ AssertDescription:
+ "'Deploy the AWS Config Management Solution' parameter must be set to 'Already Deployed', if the security hub solution
+ is being deployed."
+
+Conditions:
+ cUsingKmsKey: !Not [!Equals [!Ref pLambdaLogGroupKmsKey, '']]
+ cUseGraviton: !Or
+ - !Equals [!Ref 'AWS::Region', ap-northeast-1]
+ - !Equals [!Ref 'AWS::Region', ap-south-1]
+ - !Equals [!Ref 'AWS::Region', ap-southeast-1]
+ - !Equals [!Ref 'AWS::Region', ap-southeast-2]
+ - !Equals [!Ref 'AWS::Region', eu-central-1]
+ - !Equals [!Ref 'AWS::Region', eu-west-1]
+ - !Equals [!Ref 'AWS::Region', eu-west-2]
+ - !Equals [!Ref 'AWS::Region', us-east-1]
+ - !Equals [!Ref 'AWS::Region', us-east-2]
+ - !Equals [!Ref 'AWS::Region', us-west-2]
+
+ cCommonPrerequisitesNotInstalled: !Equals [!Ref pCommonPrerequisitesInstalled, 'false']
+ cCreateLambdaLogGroup: !Equals [!Ref pCreateLambdaLogGroup, 'Yes']
+ cDeployConfigManagementSolution: !Equals [!Ref pDeployConfigManagementSolution, 'Yes']
+ cDeployConfigManagementSolutionAlreadyDeployed: !Equals [!Ref pDeployConfigManagementSolution, 'Already Deployed']
+ cDeploySecurityHubSolution: !And
+ - !Or
+ - !Condition cDeployConfigManagementSolution
+ - !Condition cDeployConfigManagementSolutionAlreadyDeployed
+ - !Equals [!Ref pDeploySecurityHubSolution, 'Yes']
+ cDisableSecurityHub: !Equals [!Ref pDisableSecurityHub, 'Yes']
+ cCreateLogGroupAndCommonPrereqInstalled: !And
+ - !Condition cCreateLambdaLogGroup
+ - !Condition cCommonPrerequisitesNotInstalled
+
+
+Resources:
+ rCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Condition: cCommonPrerequisitesNotInstalled
+ Properties:
+ Name: !Sub '${pCodeBuildProjectName}'
+ Artifacts:
+ Type: NO_ARTIFACTS
+ Description: "Codebuild project to get SRA code from github"
+ Environment:
+ ComputeType: BUILD_GENERAL1_SMALL
+ EnvironmentVariables:
+ - Name: AWS_DEFAULT_REGION
+ Value: !Ref AWS::Region
+ - Name: AWS_ACCOUNT_ID
+ Value: !Ref "AWS::AccountId"
+ - Name: SRA_STAGING_S3_BUCKET_STACK_NAME
+ Value: !Ref pSRAStagingS3BucketStackName
+ - Name: SRA_REPO_URL
+ Value: !Ref pRepoURL
+ - Name: SRA_REPO_BRANCH_NAME
+ Value: !Ref pRepoBranch
+ Image: "aws/codebuild/standard:5.0"
+ PrivilegedMode: true
+ Type: "LINUX_CONTAINER"
+ ServiceRole: !GetAtt rCodeBuildRole.Arn
+ TimeoutInMinutes: 120
+ Source:
+ Type: NO_SOURCE
+ BuildSpec: !Sub |
+ version: 0.2
+ phases:
+ pre_build:
+ commands:
+ - echo Build started on `date`...
+ build:
+ commands:
+ - echo Build started on `date` in ${AWS::Region} region
+ - echo Cloning SRA code repository from $SRA_REPO_URL...
+ - git clone $SRA_REPO_URL
+ - echo Listing current directory...
+ - ls
+ - cd aws-security-reference-architecture-examples
+ - git checkout $SRA_REPO_BRANCH_NAME
+ - echo Showing current caller identity...
+ - aws sts get-caller-identity
+ - echo Deploying SRA staging bucket cloudformation template...
+ - aws cloudformation deploy --template-file ./aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml --stack-name $SRA_STAGING_S3_BUCKET_STACK_NAME --capabilities CAPABILITY_NAMED_IAM
+ - echo Staging SRA solutions...
+ - ./aws_sra_examples/utils/packaging_scripts/stage_solution.sh
+ post_build:
+ commands:
+ - echo Build completed on `date`
+
+ rCommonPrerequisitesManagementAccountParametersStack:
+ Type: AWS::CloudFormation::Stack
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rStartCodeBuildProjectCustomResource
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub
+ - https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-management-account-parameters.yaml
+ - SRAStagingS3BucketName: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ Tags:
+ - Key: sra-solution
+ Value: !Ref pSRASolutionName
+ Parameters:
+ pControlTower: !Ref pControlTower
+ pGovernedRegions: !Ref pGovernedRegions
+ pSecurityAccountId: !Ref pSecurityAccountId
+ pLogArchiveAccountId: !Ref pLogArchiveAccountId
+
+ rCommonPrerequisitesMainSsm:
+ Type: AWS::CloudFormation::Stack
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCommonPrerequisitesManagementAccountParametersStack
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub
+ - https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-main-ssm.yaml
+ - SRAStagingS3BucketName: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ Tags:
+ - Key: sra-solution
+ Value: !Ref pSRASolutionName
+ Parameters:
+ pCreateAWSControlTowerExecutionRole: !Ref pCreateAWSControlTowerExecutionRole
+ pControlTower: !Ref pControlTower
+
+ rCodeBuildRole:
+ Type: AWS::IAM::Role
+ Condition: cCommonPrerequisitesNotInstalled
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ - id: W11
+ reason: Allow * in resource when required
+ - id: W28
+ reason: The role name is defined to identify automation resources
+ Properties:
+ RoleName: !Sub '${pCodeBuildRoleName}'
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - codebuild.amazonaws.com
+ Action:
+ - "sts:AssumeRole"
+ Policies:
+ - PolicyName: "logs-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"
+ - PolicyName: "cloudformation-changeset-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:CreateChangeSet
+ - cloudformation:DescribeChangeSet
+ - cloudformation:ExecuteChangeSet
+ - cloudformation:GetTemplateSummary
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*"
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:changeSet/*"
+ - PolicyName: "cloudformation-describe-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:DescribeStacks
+ Resource: "*"
+ - PolicyName: "IAM-Access-Policy"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - iam:GetRole
+ - iam:PassRole
+ - iam:GetRolePolicy
+ - iam:PutRolePolicy
+ - iam:CreateRole
+ - iam:DeleteRolePolicy
+ - iam:DeleteRole
+ - iam:TagRole
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/sra*"
+ - PolicyName: "lambda-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - lambda:GetFunction
+ - lambda:GetFunctionCodeSigningConfig
+ - lambda:GetRuntimeManagementConfig
+ - lambda:CreateFunction
+ - lambda:DeleteFunction
+ - lambda:TagResource
+ - lambda:InvokeFunction
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:sra*"
+ - PolicyName: "s3-staging-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ - s3:ListBucket
+ - s3:GetBucketAcl
+ - s3:GetBucketPolicy
+ - s3:DeleteBucket
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
+ - PolicyName: "s3-create-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:PutBucketPolicy
+ - s3:PutBucketTagging
+ - s3:PutBucketPublicAccessBlock
+ - s3:GetEncryptionConfiguration
+ - s3:PutEncryptionConfiguration
+ - s3:PutBucketOwnershipControls
+ - s3:CreateBucket
+ - s3:PutBucketAcl
+ - s3:PutBucketObjectLockConfiguration
+ - s3:PutBucketVersioning
+ - s3:SetBucketEncryption
+ - s3:PutBucketEncryption
+ Resource:
+ - "arn:aws:s3:::*"
+ - PolicyName: "ssm-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - ssm:GetParameter
+ - ssm:GetParameters
+ - ssm:PutParameter
+ - ssm:AddTagsToResource
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/sra*"
+
+ rStartCodeBuildProjectCustomResource:
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCodeBuildProject
+ Type: Custom::LambdaCustomResource
+ Version: '1.0'
+ Properties:
+ ServiceToken: !GetAtt rStartCodeBuildProjectLambdaFunction.Arn
+
+ rStartCodeBuildProjectLambdaFunction:
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ - id: W58
+ reason: Lambda role provides access to CloudWatch Logs
+ - id: W89
+ reason: Lambda does not need to communicate with VPC resources.
+ - id: W92
+ reason: Lambda does not need reserved concurrent executions.
+ checkov:
+ skip:
+ - id: CKV_AWS_115
+ comment: Lambda does not need reserved concurrent executions.
+ - id: CKV_AWS_116
+ comment: DLQ not needed, as Lambda function only triggered by CloudFormation events.
+ - id: CKV_AWS_117
+ comment: Lambda does not need to communicate with VPC resources.
+ - id: CKV_AWS_173
+ comment: Environment variables are not sensitive.
+ Type: AWS::Lambda::Function
+ Condition: cCommonPrerequisitesNotInstalled
+ Properties:
+ FunctionName: !Ref pCodeBuildProjectLambdaFunctionName
+ Description: Start SRA codebuild project
+ Architectures: !If
+ - cUseGraviton
+ - [arm64]
+ - !Ref AWS::NoValue
+ Handler: index.lambda_handler
+ Role: !GetAtt rStartCodeBuildProjectLambdaRole.Arn
+ Runtime: python3.9
+ Timeout: 900
+ Environment:
+ Variables:
+ LOG_LEVEL: !Ref pLambdaLogLevel
+ CODE_BUILD_PROJECT_NAME: !Ref pCodeBuildProjectName
+ SRA_STAGING_S3_BUCKET_NAME: !Sub ${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}
+ SRA_STAGING_S3_BUCKET_STACK_NAME: !Ref pSRAStagingS3BucketStackName
+ SRA_CUSTOM_RESOURCE_NAME: !Sub ${pCodeBuildProjectLambdaFunctionName}-Custom-Resource
+ Tags:
+ - Key: !Ref pSRASolutionTagKey
+ Value: !Ref pSRASolutionName
+ Code:
+ ZipFile: |
+ # type: ignore
+ """Custom Resource to start codebuild project.
+
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: MIT-0
+ """
+ import logging
+ import os
+
+ import boto3
+ import cfnresponse
+ import time
+ from botocore.exceptions import ClientError
+
+ LOGGER = logging.getLogger(__name__)
+ log_level: str = os.environ.get("LOG_LEVEL", "INFO")
+ LOGGER.setLevel(log_level)
+ CODE_BUILD_PROJECT_NAME: str = os.environ.get("CODE_BUILD_PROJECT_NAME")
+ SRA_CUSTOM_RESOURCE_NAME: str = os.environ.get("SRA_CUSTOM_RESOURCE_NAME")
+
+
+ def start_build():
+ management_account_session = boto3.Session()
+ codebuild_client = management_account_session.client("codebuild")
+ response = codebuild_client.start_build(projectName=CODE_BUILD_PROJECT_NAME)
+ LOGGER.info({"API_Call": "codebuild:StartBuild", "API_Response": response})
+ buildId = response["build"]["id"]
+ return wait_for_build([buildId], codebuild_client)
+
+
+ def wait_for_build(BuildId, client):
+ buildWaitStatus = "FAILURE_WAIT_TIMEOUT"
+ counter = 0
+ while counter < 60:
+ time.sleep(10)
+ counter = counter + 1
+ buildStatus = get_build_status(BuildId, client)
+ if buildStatus == "SUCCEEDED":
+ buildWaitStatus = "SUCCESS"
+ break
+ elif buildStatus == "FAILED" or buildStatus == "FAULT" or buildStatus == "STOPPED" or buildStatus == "TIMED_OUT":
+ buildWaitStatus = "BUILD " + buildStatus + " (check codebuild project cloudwatch log group for details)"
+ break
+ return buildWaitStatus
+
+
+ def get_build_status(buildId, client):
+ build = client.batch_get_builds(ids=buildId)
+ return build["builds"][0]["buildStatus"]
+
+
+ def create_event(event, context):
+ try:
+ data = {"data": start_build()}
+ if data["data"] == "SUCCESS":
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, data, SRA_CUSTOM_RESOURCE_NAME)
+ else:
+ reason = f"See the details in CloudWatch Log Stream: '{context.log_group_name} and CloudFormation Events'"
+ cfnresponse.send(event, context, cfnresponse.FAILED, data, SRA_CUSTOM_RESOURCE_NAME)
+ except Exception:
+ LOGGER.exception("Unexpected!")
+ reason = f"See the details in CloudWatch Log Stream: '{context.log_group_name}'"
+ cfnresponse.send(event, context, cfnresponse.FAILED, {}, SRA_CUSTOM_RESOURCE_NAME, reason=reason)
+ return SRA_CUSTOM_RESOURCE_NAME
+
+
+ def delete_event(event, context):
+ LOGGER.info("entered delete_event function. Nothing to do...")
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, {"delete_operation": "succeeded deleting"}, SRA_CUSTOM_RESOURCE_NAME)
+
+
+ def lambda_handler(event, context):
+ LOGGER.info(event)
+ if event["RequestType"] == "Create":
+ LOGGER.info("CREATE EVENT!!")
+ create_event(event, context)
+ if event["RequestType"] == "Update":
+ LOGGER.info("UPDATE EVENT!!")
+
+ if event["RequestType"] == "Delete":
+ LOGGER.info("DELETE EVENT!!")
+ delete_event(event, context)
+
+
+ rStartCodeBuildProjectLambdaLogGroup:
+ DeletionPolicy: Retain
+ Type: AWS::Logs::LogGroup
+ Condition: cCommonPrerequisitesNotInstalled
+ UpdateReplacePolicy: Retain
+ Properties:
+ LogGroupName: !Sub /aws/lambda/${pCodeBuildProjectLambdaFunctionName}
+ KmsKeyId: !If
+ - cUsingKmsKey
+ - !Ref pLambdaLogGroupKmsKey
+ - !Ref AWS::NoValue
+ RetentionInDays: !Ref pLambdaLogGroupRetention
+
+ rStartCodeBuildProjectLambdaRole:
+ Type: AWS::IAM::Role
+ Condition: cCommonPrerequisitesNotInstalled
+ Metadata:
+ cfn_nag:
+ rules_to_suppress:
+ # - id: W11
+ # reason: Allow * in resource when required
+ - id: W28
+ reason: The role name is defined to identify automation resources
+ Properties:
+ RoleName: !Ref pCodeBuildProjectLambdaRoleName
+ Description: !Sub Role for '${pCodeBuildProjectLambdaRoleName}' Lambda function
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action: sts:AssumeRole
+ Principal:
+ Service:
+ - lambda.amazonaws.com
+ Tags:
+ - Key: !Ref pSRASolutionTagKey
+ Value: !Ref pSRASolutionName
+ Policies:
+ - PolicyName: codebuild-access
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Sid: codebuildStartBuild
+ Effect: Allow
+ Action:
+ - codebuild:StartBuild
+ - codebuild:BatchGetBuilds
+ Resource: !GetAtt rCodeBuildProject.Arn
+ - PolicyName: CloudWatchLogGroup-access
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Sid: CloudWatchLogs
+ Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pCodeBuildProjectLambdaFunctionName}:log-stream:*
+ - PolicyName: "s3-staging-bucket-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ - s3:ListBucket
+ - s3:GetBucketAcl
+ - s3:GetBucketPolicy
+ - s3:GetObjectAcl
+ - s3:PutObjectAcl
+ - s3:DeleteBucket
+ - s3:DeleteObject
+ - s3:DeleteObjectVersion
+ - s3:GetBucketVersioning
+ - s3:DeleteBucketPolicy
+ - s3:ListBucketVersions
+ - s3:PutBucketVersioning
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
+ - !Sub "arn:${AWS::Partition}:s3:::${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
+ - PolicyName: "lambda-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - lambda:DeleteFunction
+ - lambda:InvokeFunction
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:sra*"
+ - PolicyName: "cloudformation-stack-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - cloudformation:DeleteStack
+ - cloudformation:DescribeStacks
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/sra*"
+ - PolicyName: "IAM-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - iam:DeleteRole
+ - iam:DeleteRolePolicy
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/sra*"
+
+
+ rSecurityHubSolutionStack:
+ Type: AWS::CloudFormation::Stack
+ DependsOn: WaitCondition
+ Condition: cDeploySecurityHubSolution
+ DeletionPolicy: Delete
+ UpdateReplacePolicy: Delete
+ Properties:
+ TemplateURL: !Sub https://${pSRAStagingS3BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}.s3.${AWS::Region}.${AWS::URLSuffix}/sra-securityhub-org/templates/sra-securityhub-org-main-ssm.yaml
+ Parameters:
+ pCISStandardVersion: !Ref pCISStandardVersion
+ pComplianceFrequency: !Ref pComplianceFrequency
+ pCreateLambdaLogGroup: !If [cCreateLambdaLogGroup, true, false]
+ pDisableSecurityHub: !If [cDisableSecurityHub, true, false]
+ pEnableCISStandard: !Ref pEnableCISStandard
+ pEnablePCIStandard: !Ref pEnablePCIStandard
+ pEnableSecurityBestPracticesStandard: !Ref pEnableSecurityBestPracticesStandard
+ pLambdaLogGroupKmsKey: !Ref pLambdaLogGroupKmsKey
+ pLambdaLogGroupRetention: !Ref pLambdaLogGroupRetention
+ pLambdaLogLevel: !Ref pLambdaLogLevel
+ pRegionLinkingMode: !Ref pRegionLinkingMode
+ pSRAAlarmEmail: !Ref pSRAAlarmEmail
+ pEnableNISTStandard: !Ref pEnableNISTStandard
+ pNISTStandardVersion: !Ref pNISTStandardVersion
+
+ CommonPrerequisitesMainSsmWaitHandle:
+ Condition: cCommonPrerequisitesNotInstalled
+ DependsOn: rCommonPrerequisitesMainSsm
+ Type: "AWS::CloudFormation::WaitConditionHandle"
+
+ WaitHandle:
+ Type: "AWS::CloudFormation::WaitConditionHandle"
+
+ WaitCondition:
+ Type: "AWS::CloudFormation::WaitCondition"
+ Properties:
+ Handle: !If [cCommonPrerequisitesNotInstalled, !Ref CommonPrerequisitesMainSsmWaitHandle, !Ref WaitHandle]
+ Timeout: "1"
+ Count: 0
+
+Outputs:
+ oAuditAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Audit Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oAuditAccountId]
+ oCustomerControlTowerRegions:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Customer Control Tower Regions
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oCustomerControlTowerRegions]
+ oEnabledRegions:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Enabled Regions
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oEnabledRegions]
+ oEnabledRegionsWithoutHomeRegion:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Enabled Regions without Home Region
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oEnabledRegionsWithoutHomeRegion]
+ oHomeRegion:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Control Tower Home Region
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oHomeRegion]
+ oLogArchiveAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Log Archive Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oLogArchiveAccountId]
+ oManagementAccountId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountId]
+ oRootOrganizationalUnitId:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Root Organizational Unit ID
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oRootOrganizationalUnitId]
+ oManagementAccountParametersLambdaFunctionArn:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account Parameters Lambda Function ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaFunctionArn]
+ oManagementAccountParametersLambdaLogGroupArn:
+ Condition: cCreateLogGroupAndCommonPrereqInstalled
+ Description: Management Account Parameters Lambda Log Group ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaLogGroupArn]
+ oManagementAccountParametersLambdaRoleArn:
+ Condition: cCommonPrerequisitesNotInstalled
+ Description: Management Account Parameters Lambda Role ARN
+ Value: !GetAtt [rCommonPrerequisitesManagementAccountParametersStack, Outputs.oManagementAccountParametersLambdaRoleArn]
\ No newline at end of file
diff --git a/aws_sra_examples/quick_setup/customizations_for_aws_control_tower/manifest-v2.yaml b/aws_sra_examples/quick_setup/customizations_for_aws_control_tower/manifest-v2.yaml
index 649bc537..ec0861d9 100644
--- a/aws_sra_examples/quick_setup/customizations_for_aws_control_tower/manifest-v2.yaml
+++ b/aws_sra_examples/quick_setup/customizations_for_aws_control_tower/manifest-v2.yaml
@@ -185,7 +185,7 @@ resources:
- parameter_key: pDeployInspectorSolution
parameter_value: 'Yes'
- parameter_key: pScanComponents
- parameter_value: 'EC2, ECR, LAMBDA'
+ parameter_value: 'EC2, ECR, LAMBDA, LAMBDA_CODE'
- parameter_key: pEcrRescanDuration
parameter_value: 'LIFETIME'
diff --git a/aws_sra_examples/quick_setup/templates/sra-quick-setup-ssm.yaml b/aws_sra_examples/quick_setup/templates/sra-quick-setup-ssm.yaml
index 63a07a2c..34ba7422 100644
--- a/aws_sra_examples/quick_setup/templates/sra-quick-setup-ssm.yaml
+++ b/aws_sra_examples/quick_setup/templates/sra-quick-setup-ssm.yaml
@@ -358,7 +358,7 @@ Metadata:
pSRAStagingS3BucketName:
default: SRA Staging S3 Bucket Name
pScanComponents:
- default: Comma separated list of scan components (EC2, ECR, LAMBDA)
+ default: Comma separated list of scan components (EC2, ECR, LAMBDA, LAMBDA_CODE)
pSecurityContactAction:
default: Security Alternate Contact Action
pSecurityEmail:
@@ -929,8 +929,8 @@ Parameters:
name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
Type: AWS::SSM::Parameter::Value
pScanComponents:
- AllowedValues: [EC2, ECR, LAMBDA]
- Default: EC2, ECR, LAMBDA
+ AllowedValues: [EC2, ECR, LAMBDA, LAMBDA_CODE]
+ Default: EC2, ECR, LAMBDA, LAMBDA_CODE
Description: Lambda Function Logging Level
Type: CommaDelimitedList
pSecurityContactAction:
diff --git a/aws_sra_examples/solutions/account/account_alternate_contacts/README.md b/aws_sra_examples/solutions/account/account_alternate_contacts/README.md
index e64d17c2..f6816389 100644
--- a/aws_sra_examples/solutions/account/account_alternate_contacts/README.md
+++ b/aws_sra_examples/solutions/account/account_alternate_contacts/README.md
@@ -100,7 +100,7 @@ The Account Alternate Contacts solution sets alternate contacts for all existing
#### 2.2 Configuration IAM Role
-- See [1.3 Configuration IAM Role](#13-configuration-iam-role)
+- See [1.2 IAM Role](#12-iam-roles)
#### 2.3 Account Alternate Contacts
diff --git a/aws_sra_examples/solutions/account/account_alternate_contacts/documentation/account-alternate-contacts.pptx b/aws_sra_examples/solutions/account/account_alternate_contacts/documentation/account-alternate-contacts.pptx
index 65dabba3..6e1fb186 100644
Binary files a/aws_sra_examples/solutions/account/account_alternate_contacts/documentation/account-alternate-contacts.pptx and b/aws_sra_examples/solutions/account/account_alternate_contacts/documentation/account-alternate-contacts.pptx differ
diff --git a/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-main-ssm.yaml b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-main-ssm.yaml
index 69fd440e..d4cec19e 100644
--- a/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-main-ssm.yaml
+++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-main-ssm.yaml
@@ -331,3 +331,15 @@ Resources:
pLambdaLogLevel: !Ref pLambdaLogLevel
pOrganizationCloudTrailKMSKeyId: !Sub '{{resolve:secretsmanager:arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${pAuditAccountId}:secret:sra/cloudtrail_org_key_arn:SecretString:OrganizationCloudTrailKeyArn:AWSCURRENT}}'
pSRAStagingS3BucketName: !Ref pSRAStagingS3BucketName
+
+Outputs:
+ oOrganizationCloudTrailS3BucketName:
+ Description: Organization CloudTrail S3 Bucket Name
+ Value: !Sub ${pBucketNamePrefix}-${pLogArchiveAccountId}-${AWS::Region}
+ Export:
+ Name: eOrganizationCloudTrailS3BucketName
+ oOrganizationCloudTrailS3BucketArn:
+ Description: Organization CloudTrail S3 Bucket Arn
+ Value: !Sub arn:${AWS::Partition}:s3:::${pBucketNamePrefix}-${pLogArchiveAccountId}-${AWS::Region}
+ Export:
+ Name: eOrganizationCloudTrailS3BucketArn
\ No newline at end of file
diff --git a/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-main-ssm.yaml b/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-main-ssm.yaml
index 6c2de7a0..17f89b1d 100644
--- a/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-main-ssm.yaml
+++ b/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-main-ssm.yaml
@@ -252,8 +252,8 @@ Resources:
rControlTowerExecutionRoleStack:
Type: AWS::CloudFormation::Stack
Condition: cAWSControlTowerPlusExecutionRole
- DeletionPolicy: Delete
- UpdateReplacePolicy: Delete
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Properties:
TemplateURL: !Sub
- https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-control-tower-execution-role.yaml
@@ -265,8 +265,8 @@ Resources:
rExecutionRoleStack:
Type: AWS::CloudFormation::Stack
DependsOn: rAdminRoleStack
- DeletionPolicy: Delete
- UpdateReplacePolicy: Delete
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Properties:
TemplateURL: !Sub
- https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-stackset-execution-role.yaml
@@ -279,8 +279,8 @@ Resources:
rAdminRoleStack:
Type: AWS::CloudFormation::Stack
- DeletionPolicy: Delete
- UpdateReplacePolicy: Delete
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Properties:
TemplateURL: !Sub
- https://${SRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/sra-common-prerequisites-stackset-admin-role.yaml
@@ -293,6 +293,8 @@ Resources:
rExecutionRoleStackSet:
DependsOn: rAdminRoleStack
Type: AWS::CloudFormation::StackSet
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Properties:
StackSetName: sra-stackset-execution-role
AutoDeployment:
diff --git a/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-management-account-parameters.yaml b/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-management-account-parameters.yaml
index 19acd2e4..c2817c98 100644
--- a/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-management-account-parameters.yaml
+++ b/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-management-account-parameters.yaml
@@ -315,40 +315,59 @@ Outputs:
oAuditAccountId:
Description: Audit Account ID
Value: !GetAtt rManagementAccountParametersLambdaCustomResource.AuditAccountId
+ Export:
+ Name: eAuditAccountId
oCustomerControlTowerRegions:
Description: Customer Control Tower Regions
Value: !Join [',', !GetAtt rManagementAccountParametersLambdaCustomResource.CustomerControlTowerRegions]
- oCustomerControlTowerRegionsWithoutHomeRegion:
- Description: Customer Control Tower Regions without Home Region
- Value: !Join [',', !GetAtt rManagementAccountParametersLambdaCustomResource.CustomerControlTowerRegionsWithoutHomeRegion]
+ Export:
+ Name: eCustomerControlTowerRegions
oEnabledRegions:
Description: Enabled Regions
Value: !Join [',', !GetAtt rManagementAccountParametersLambdaCustomResource.EnabledRegions]
+ Export:
+ Name: eEnabledRegions
oEnabledRegionsWithoutHomeRegion:
Description: Enabled Regions without Home Region
Value: !Join [',', !GetAtt rManagementAccountParametersLambdaCustomResource.EnabledRegionsWithoutHomeRegion]
+ Export:
+ Name: eEnabledRegionsWithoutHomeRegion
oHomeRegion:
Description: Control Tower Home Region
Value: !GetAtt rManagementAccountParametersLambdaCustomResource.HomeRegion
+ Export:
+ Name: eHomeRegion
oLogArchiveAccountId:
Description: Log Archive Account ID
Value: !GetAtt rManagementAccountParametersLambdaCustomResource.LogArchiveAccountId
+ Export:
+ Name: eLogArchiveAccountId
oManagementAccountId:
Description: Management Account ID
Value: !GetAtt rManagementAccountParametersLambdaCustomResource.ManagementAccountId
+ Export:
+ Name: eManagementAccountId
oOrganizationId:
Description: Organization ID
Value: !GetAtt rManagementAccountParametersLambdaCustomResource.OrganizationId
oRootOrganizationalUnitId:
Description: Root Organizational Unit ID
Value: !GetAtt rManagementAccountParametersLambdaCustomResource.RootOrganizationalUnitId
+ Export:
+ Name: eRootOrganizationalUnitId
oManagementAccountParametersLambdaFunctionArn:
Description: Management Account Parameters Lambda Function ARN
Value: !GetAtt rManagementAccountParametersLambdaFunction.Arn
+ Export:
+ Name: eManagementAccountParametersLambdaFunctionArn
oManagementAccountParametersLambdaLogGroupArn:
Condition: cCreateLambdaLogGroup
Description: Management Account Parameters Lambda Log Group ARN
Value: !GetAtt rManagementAccountParametersLambdaLogGroup.Arn
+ Export:
+ Name: eManagementAccountParametersLambdaLogGroupArn
oManagementAccountParametersLambdaRoleArn:
Description: Management Account Parameters Lambda Role ARN
Value: !GetAtt rManagementAccountParametersLambdaRole.Arn
+ Export:
+ Name: eManagementAccountParametersLambdaRoleArn
diff --git a/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml b/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml
index a25bd959..9ea30d8a 100644
--- a/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml
+++ b/aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml
@@ -296,6 +296,8 @@ Resources:
rSRAStagingS3Bucket:
Type: AWS::S3::Bucket
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Metadata:
cfn_nag:
rules_to_suppress:
@@ -403,21 +405,33 @@ Outputs:
Condition: cCreateCustomResource
Description: Organization ID
Value: !GetAtt rOrgIdLambdaCustomResource.OrganizationId
+ Export:
+ Name: eOrganizationId
oOrgIdLambdaFunctionArn:
Condition: cCreateCustomResource
Description: AWS Organization ID Lambda Function ARN
Value: !GetAtt rOrgIdLambdaFunction.Arn
+ Export:
+ Name: eOrgIdLambdaFunctionArn
oOrgIdLambdaLogGroupArn:
Condition: cCreateLambdaLogGroupAndCreateCustomResource
Description: AWS Organization ID Lambda Log Group ARN
Value: !GetAtt rOrgIdLambdaLogGroup.Arn
+ Export:
+ Name: eOrgIdLambdaLogGroupArn
oOrgIdLambdaRoleArn:
Condition: cCreateCustomResource
Description: AWS Organization ID Lambda Role ARN
Value: !GetAtt rOrgIdLambdaRole.Arn
+ Export:
+ Name: eOrgIdLambdaRoleArn
oSRAStagingS3BucketName:
Description: SRA Staging S3 Bucket Name SSM parameter
Value: !GetAtt rSSMParameterSRAStagingS3BucketName.Value
+ Export:
+ Name: eSRAStagingS3BucketName
oSRAStagingS3BucketNamePrefix:
Description: SRA Staging S3 Bucket Name Prefix SSM parameter
Value: !GetAtt rSSMParameterSRAStagingS3BucketNamePrefix.Value
+ Export:
+ Name: eSRAStagingS3BucketNamePrefix
diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md b/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md
index 692d8dd4..ea68db8a 100644
--- a/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md
+++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md
@@ -58,10 +58,9 @@ evaluate your AWS environment, use one of the sample conformance pack templates.
---
-### 3.0 Audit Account
+### 3.0 Audit Account (Security Tooling)
-The example solutions use `Audit Account` instead of `Security Tooling Account` to align with the default account name used within the AWS Control Tower setup process for the Security Account. The Account ID for the `Audit Account` SSM parameter is
-populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-BASELINE-CONFIG` StackSet.
+The example solutions use `Audit Account` instead of `Security Tooling Account` to align with the default account name used within the AWS Control Tower setup process for the Security Account. The Account ID for the `Audit Account` can be determined from the `SecurityAccountId` parameter within the `AWSControlTowerBP-BASELINE-CONFIG` StackSet in AWS Control Tower environments, but is specified manually in other environments, and then stored in an SSM parameter (this is all done in the common prerequisites solution).
#### 3.1 AWS CloudFormation
diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/scripts/list_config_recorder_status.py b/aws_sra_examples/solutions/config/config_conformance_pack_org/scripts/list_config_recorder_status.py
index e7801e19..d6ba1525 100644
--- a/aws_sra_examples/solutions/config/config_conformance_pack_org/scripts/list_config_recorder_status.py
+++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/scripts/list_config_recorder_status.py
@@ -26,6 +26,7 @@
if TYPE_CHECKING:
from mypy_boto3_cloudformation import CloudFormationClient
from mypy_boto3_organizations import OrganizationsClient
+ from mypy_boto3_ssm.client import SSMClient
from mypy_boto3_sts.client import STSClient
# Logging Settings
@@ -34,18 +35,17 @@
logging.getLogger("botocore").setLevel(logging.CRITICAL)
# Global Variables
-CLOUDFORMATION_PAGE_SIZE = 20
-CLOUDFORMATION_THROTTLE_PERIOD = 0.2
MAX_THREADS = 20
ORG_PAGE_SIZE = 20 # Max page size for list_accounts
ORG_THROTTLE_PERIOD = 0.2
-ASSUME_ROLE_NAME = "AWSControlTowerExecution"
+ASSUME_ROLE_NAME = "sra-execution"
BOTO3_CONFIG = Config(retries={"max_attempts": 10, "mode": "standard"})
try:
MANAGEMENT_ACCOUNT_SESSION = boto3.Session()
ORG_CLIENT: OrganizationsClient = MANAGEMENT_ACCOUNT_SESSION.client("organizations", config=BOTO3_CONFIG)
CFN_CLIENT: CloudFormationClient = MANAGEMENT_ACCOUNT_SESSION.client("cloudformation", config=BOTO3_CONFIG)
+ SSM_CLIENT: SSMClient = MANAGEMENT_ACCOUNT_SESSION.client("ssm")
except Exception as error:
LOGGER.error({"Unexpected_Error": error})
raise ValueError("Unexpected error executing Lambda function. Review CloudWatch logs for details.") from None
@@ -101,29 +101,14 @@ def get_all_organization_accounts() -> list:
def get_control_tower_regions() -> list: # noqa: CCR001
- """Query 'AWSControlTowerBP-BASELINE-CLOUDWATCH' CloudFormation stack to identify customer regions.
+ """Query SSM Parameter Store to identify customer regions.
Returns:
- Customer regions chosen in Control Tower
+ Customer regions
"""
- paginator = CFN_CLIENT.get_paginator("list_stack_instances")
- customer_regions = set()
- aws_account = ""
- all_regions_identified = False
- for page in paginator.paginate(StackSetName="AWSControlTowerBP-BASELINE-CLOUDWATCH", PaginationConfig={"PageSize": CLOUDFORMATION_PAGE_SIZE}):
- for instance in page["Summaries"]:
- if not aws_account:
- aws_account = instance["Account"]
- customer_regions.add(instance["Region"])
- continue
- if aws_account == instance["Account"]:
- customer_regions.add(instance["Region"])
- continue
- all_regions_identified = True
- break
- if all_regions_identified:
- break
- sleep(CLOUDFORMATION_THROTTLE_PERIOD)
+ customer_regions = []
+ ssm_response = SSM_CLIENT.get_parameter(Name="/sra/regions/customer-control-tower-regions")
+ customer_regions = ssm_response["Parameter"]["Value"].split(",")
return list(customer_regions)
diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml
index 97e6226f..da3223d9 100644
--- a/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml
+++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml
@@ -94,7 +94,7 @@ Resources:
StringLike:
aws:PrincipalArn:
- !Sub arn:${AWS::Partition}:iam::*:role/aws-service-role/config-conforms.amazonaws.com/AWSServiceRoleForConfigConforms
- - !Sub arn:${AWS::Partition}:iam::*:role/AWSControlTowerExecution
+ - !Sub arn:${AWS::Partition}:iam::*:role/sra-execution
Resource: !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket}
Principal: '*'
diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main-ssm.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main-ssm.yaml
index 4c40ab79..9af8ed82 100644
--- a/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main-ssm.yaml
+++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main-ssm.yaml
@@ -20,6 +20,12 @@ Metadata:
- pSRAStagingS3BucketName
- pSourceStackName
+ - Label:
+ default: IAM Properties
+ Parameters:
+ - pStackSetAdminRole
+ - pStackExecutionRole
+
- Label:
default: Conformance Pack Properties
Parameters:
@@ -38,6 +44,10 @@ Metadata:
- pOrganizationId
ParameterLabels:
+ pStackSetAdminRole:
+ default: Stack Set Role
+ pStackExecutionRole:
+ default: Stack execution role
pAuditAccountId:
default: Audit Account ID
pConformancePackName:
@@ -66,6 +76,16 @@ Metadata:
default: SRA Staging S3 Bucket Name
Parameters:
+ pStackSetAdminRole:
+ AllowedValues: [sra-stackset]
+ Default: sra-stackset
+ Description: The administration role name that is used in the stackset.
+ Type: String
+ pStackExecutionRole:
+ AllowedValues: [sra-execution]
+ Default: sra-execution
+ Description: The execution role name that is used in the stack.
+ Type: String
pAuditAccountId:
AllowedPattern: ^([\w.-]{1,900})$|^(\/[\w.-]{1,900})*[\w.-]{1,900}$
ConstraintDescription:
@@ -176,10 +196,10 @@ Resources:
Type: AWS::CloudFormation::StackSet
Properties:
StackSetName: sra-config-conformance-pack-org-delivery-bucket
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Description: !Sub ${pSRASolutionVersion} - Creates S3 bucket to store the conformance pack results
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
@@ -208,7 +228,7 @@ Resources:
DependsOn: rConfigConformancePackOrgDeliveryBucketStackSet
Properties:
StackSetName: sra-config-conformance-pack-org-deployment
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Description: !If
- cRegisterDelegatedAdmin
@@ -220,7 +240,7 @@ Resources:
]
- !Sub ${pSRASolutionVersion} - This template creates an AWS Organizations Config Conformance Pack in the Control Tower Audit account. -
'config_conformance_pack_org' solution in repo, https://github.com/aws-samples/aws-security-reference-architecture-examples.
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main.yaml
index db6f9a75..11935780 100644
--- a/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main.yaml
+++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-main.yaml
@@ -18,6 +18,12 @@ Metadata:
- pSRAStagingS3BucketName
- pSRASolutionVersion
+ - Label:
+ default: IAM Properties
+ Parameters:
+ - pStackSetAdminRole
+ - pStackExecutionRole
+
- Label:
default: Conformance Pack Properties
Parameters:
@@ -36,6 +42,10 @@ Metadata:
- pOrganizationId
ParameterLabels:
+ pStackSetAdminRole:
+ default: Stack Set Role
+ pStackExecutionRole:
+ default: Stack execution role
pAuditAccountId:
default: Audit Account ID
pConformancePackName:
@@ -62,6 +72,16 @@ Metadata:
default: SRA Staging S3 Bucket Name
Parameters:
+ pStackSetAdminRole:
+ AllowedValues: [sra-stackset]
+ Default: sra-stackset
+ Description: The administration role name that is used in the stackset.
+ Type: String
+ pStackExecutionRole:
+ AllowedValues: [sra-execution]
+ Default: sra-execution
+ Description: The execution role name that is used in the stack.
+ Type: String
pAuditAccountId:
AllowedPattern: ^([\w.-]{1,900})$|^(\/[\w.-]{1,900})*[\w.-]{1,900}$
ConstraintDescription:
@@ -163,10 +183,10 @@ Resources:
Type: AWS::CloudFormation::StackSet
Properties:
StackSetName: sra-config-conformance-pack-org-delivery-bucket
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Description: !Sub ${pSRASolutionVersion} - Creates S3 bucket to store the conformance pack results
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
@@ -195,7 +215,7 @@ Resources:
DependsOn: rConfigConformancePackOrgDeliveryBucketStackSet
Properties:
StackSetName: sra-config-conformance-pack-org-deployment
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Description: !If
- cRegisterDelegatedAdmin
@@ -207,7 +227,7 @@ Resources:
]
- !Sub ${pSRASolutionVersion} - This template creates an AWS Organizations Config Conformance Pack in the Control Tower Audit account. -
'config_conformance_pack_org' solution in repo, https://github.com/aws-samples/aws-security-reference-architecture-examples.
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
diff --git a/aws_sra_examples/solutions/config/config_management_account/README.md b/aws_sra_examples/solutions/config/config_management_account/README.md
index c3a8efac..c59005fc 100644
--- a/aws_sra_examples/solutions/config/config_management_account/README.md
+++ b/aws_sra_examples/solutions/config/config_management_account/README.md
@@ -74,10 +74,10 @@ accounts/regions.
---
-### 2.0 Audit Account
+### 2.0 Audit Account (Security Tooling)
+
+The example solutions use `Audit Account` instead of `Security Tooling Account` to align with the default account name used within the AWS Control Tower setup process for the Security Account. The Account ID for the `Audit Account` can be determined from the `SecurityAccountId` parameter within the `AWSControlTowerBP-BASELINE-CONFIG` StackSet in AWS Control Tower environments, but is specified manually in other environments, and then stored in an SSM parameter (this is all done in the common prerequisites solution).
-The example solutions use `Audit Account` instead of `Security Tooling Account` to align with the default account name used within the AWS Control Tower setup process for the Security Account. The Account ID for the `Audit Account` SSM parameter is
-populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-BASELINE-CONFIG` StackSet.
#### 2.1 AWS Config Aggregator
diff --git a/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main-ssm.yaml b/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main-ssm.yaml
index b0fe73bc..f3814f5b 100644
--- a/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main-ssm.yaml
+++ b/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main-ssm.yaml
@@ -25,6 +25,11 @@ Metadata:
- pLogArchiveAccountId
- pOrganizationId
- pHomeRegion
+ - Label:
+ default: IAM Properties
+ Parameters:
+ - pStackSetAdminRole
+ - pStackExecutionRole
- Label:
default: Config Recorder Properties
Parameters:
@@ -45,6 +50,10 @@ Metadata:
- pLambdaLogGroupKmsKey
- pLambdaLogLevel
ParameterLabels:
+ pStackSetAdminRole:
+ default: Stack Set Role
+ pStackExecutionRole:
+ default: Stack execution role
pAllSupported:
default: All Supported
pAuditAccountId:
@@ -81,6 +90,16 @@ Metadata:
default: SRA Staging S3 Bucket Name
Parameters:
+ pStackSetAdminRole:
+ AllowedValues: [sra-stackset]
+ Default: sra-stackset
+ Description: The administration role name that is used in the stackset.
+ Type: String
+ pStackExecutionRole:
+ AllowedValues: [sra-execution]
+ Default: sra-execution
+ Description: The execution role name that is used in the stack.
+ Type: String
pAllSupported:
AllowedValues: ['true', 'false']
Default: 'true'
@@ -214,10 +233,10 @@ Resources:
Type: AWS::CloudFormation::StackSet
Properties:
StackSetName: sra-config-management-account
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Description: !Sub ${pSRASolutionVersion} - Enables AWS Config in the Control Tower Management account.
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
diff --git a/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main.yaml b/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main.yaml
index 7518a3cd..915c3158 100644
--- a/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main.yaml
+++ b/aws_sra_examples/solutions/config/config_management_account/templates/sra-config-management-account-main.yaml
@@ -24,6 +24,11 @@ Metadata:
- pLogArchiveAccountId
- pOrganizationId
- pHomeRegion
+ - Label:
+ default: IAM Properties
+ Parameters:
+ - pStackSetAdminRole
+ - pStackExecutionRole
- Label:
default: Config Recorder Properties
Parameters:
@@ -44,6 +49,10 @@ Metadata:
- pLambdaLogGroupKmsKey
- pLambdaLogLevel
ParameterLabels:
+ pStackSetAdminRole:
+ default: Stack Set Role
+ pStackExecutionRole:
+ default: Stack execution role
pAllSupported:
default: All Supported
pAuditAccountId:
@@ -80,6 +89,16 @@ Metadata:
default: SRA Staging S3 Bucket Name
Parameters:
+ pStackSetAdminRole:
+ AllowedValues: [sra-stackset]
+ Default: sra-stackset
+ Description: The administration role name that is used in the stackset.
+ Type: String
+ pStackExecutionRole:
+ AllowedValues: [sra-execution]
+ Default: sra-execution
+ Description: The execution role name that is used in the stack.
+ Type: String
pAllSupported:
AllowedValues: ['true', 'false']
Default: 'true'
@@ -204,10 +223,10 @@ Resources:
Type: AWS::CloudFormation::StackSet
Properties:
StackSetName: sra-config-management-account
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Description: !Sub ${pSRASolutionVersion} - Enables AWS Config in the Control Tower Management account.
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
diff --git a/aws_sra_examples/solutions/detective/detective_org/README.md b/aws_sra_examples/solutions/detective/detective_org/README.md
index 319dd0fc..35f19b02 100644
--- a/aws_sra_examples/solutions/detective/detective_org/README.md
+++ b/aws_sra_examples/solutions/detective/detective_org/README.md
@@ -78,11 +78,11 @@ The Detective Organization solution will automate enabling Amazon Detective by d
---
-### 2.0 Audit Account
+### 2.0 Audit Account (Security Tooling)
The example solutions use `Audit Account` instead of `Security Tooling Account` to align with the default account name used within the AWS Control Tower
setup process for the Security Account. The Account ID for the `Audit Account` SSM parameter is
-populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-BASELINE-CONFIG` StackSet.
+populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-BASELINE-CONFIG` StackSet, but is specified manually in other environments, and then stored in an SSM parameter (this is all done in the common prerequisites solution).
#### 2.1 AWS CloudFormation
diff --git a/aws_sra_examples/solutions/detective/detective_org/lambda/src/common.py b/aws_sra_examples/solutions/detective/detective_org/lambda/src/common.py
index 8dfea8ab..92f7b0c9 100644
--- a/aws_sra_examples/solutions/detective/detective_org/lambda/src/common.py
+++ b/aws_sra_examples/solutions/detective/detective_org/lambda/src/common.py
@@ -16,9 +16,9 @@
from botocore.exceptions import ClientError, EndpointConnectionError
if TYPE_CHECKING:
- from mypy_boto3_cloudformation import CloudFormationClient
from mypy_boto3_iam.client import IAMClient
from mypy_boto3_organizations import OrganizationsClient
+ from mypy_boto3_ssm.client import SSMClient
from mypy_boto3_sts.client import STSClient
# Setup Default Logger
@@ -27,15 +27,13 @@
LOGGER.setLevel(log_level)
# Global variables
-CLOUDFORMATION_PAGE_SIZE = 20
-CLOUDFORMATION_THROTTLE_PERIOD = 0.2
ORGANIZATIONS_PAGE_SIZE = 20
ORGANIZATIONS_THROTTLE_PERIOD = 0.2
try:
MANAGEMENT_ACCOUNT_SESSION = boto3.Session()
- CLOUDFORMATION_CLIENT: CloudFormationClient = MANAGEMENT_ACCOUNT_SESSION.client("cloudformation")
ORG_CLIENT: OrganizationsClient = MANAGEMENT_ACCOUNT_SESSION.client("organizations")
+ SSM_CLIENT: SSMClient = MANAGEMENT_ACCOUNT_SESSION.client("ssm")
except Exception as error:
LOGGER.error({"Unexpected_Error": error})
raise ValueError("Unexpected error executing Lambda function. Review CloudWatch logs for details.") from None
@@ -101,32 +99,13 @@ def get_active_organization_accounts(exclude_accounts: list = None) -> list:
def get_control_tower_regions() -> list: # noqa: CCR001
- """Query 'AWSControlTowerBP-BASELINE-CLOUDWATCH' CloudFormation stack to identify customer regions.
+ """Query SSM Parameter Store to identify customer regions.
Returns:
- Customer regions chosen in Control Tower
+ Customer regions
"""
- paginator = CLOUDFORMATION_CLIENT.get_paginator("list_stack_instances")
- customer_regions = []
- aws_account = ""
- all_regions_identified = False
- for page in paginator.paginate(
- StackSetName="AWSControlTowerBP-BASELINE-CLOUDWATCH",
- PaginationConfig={"PageSize": CLOUDFORMATION_PAGE_SIZE},
- ):
- for instance in page["Summaries"]:
- if not aws_account:
- aws_account = instance["Account"]
- customer_regions.append(instance["Region"])
- continue
- if aws_account == instance["Account"]:
- customer_regions.append(instance["Region"])
- continue
- all_regions_identified = True
- break
- if all_regions_identified:
- break
- sleep(CLOUDFORMATION_THROTTLE_PERIOD)
+ ssm_response = SSM_CLIENT.get_parameter(Name="/sra/regions/customer-control-tower-regions")
+ customer_regions = ssm_response["Parameter"]["Value"].split(",")
return list(customer_regions)
diff --git a/aws_sra_examples/solutions/detective/detective_org/templates/sra-detective-org-configuration.yaml b/aws_sra_examples/solutions/detective/detective_org/templates/sra-detective-org-configuration.yaml
index c0fe88e7..40ae11c9 100644
--- a/aws_sra_examples/solutions/detective/detective_org/templates/sra-detective-org-configuration.yaml
+++ b/aws_sra_examples/solutions/detective/detective_org/templates/sra-detective-org-configuration.yaml
@@ -281,6 +281,18 @@ Resources:
- detective:DisableOrganizationAdminAccount
- detective:ListOrganizationAdminAccount
Resource: '*'
+
+ - PolicyName: "ssm-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - ssm:GetParameter
+ - ssm:GetParameters
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/sra*"
+
- PolicyName: sra-detective-org-policy-iam
PolicyDocument:
Version: 2012-10-17
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.png b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.png
index d2ff464d..a668ee5f 100644
Binary files a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.png and b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.png differ
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.pptx b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.pptx
index e1cec17f..e8e095bf 100644
Binary files a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.pptx and b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/documentation/ec2-default-ebs-encryption.pptx differ
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/lambda/src/app.py b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/lambda/src/app.py
index 131fbee1..cc630796 100644
--- a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/lambda/src/app.py
+++ b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/lambda/src/app.py
@@ -31,6 +31,7 @@
from mypy_boto3_organizations.type_defs import AccountTypeDef, DescribeAccountResponseTypeDef, TagTypeDef
from mypy_boto3_sns import SNSClient
from mypy_boto3_sns.type_defs import PublishBatchResponseTypeDef, PublishResponseTypeDef
+ from mypy_boto3_ssm.client import SSMClient
from mypy_boto3_sts import STSClient
# Setup Default Logger
@@ -55,6 +56,7 @@
CFN_CLIENT: CloudFormationClient = MANAGEMENT_ACCOUNT_SESSION.client("cloudformation", config=BOTO3_CONFIG)
ORG_CLIENT: OrganizationsClient = MANAGEMENT_ACCOUNT_SESSION.client("organizations", config=BOTO3_CONFIG)
SNS_CLIENT: SNSClient = MANAGEMENT_ACCOUNT_SESSION.client("sns", config=BOTO3_CONFIG)
+ SSM_CLIENT: SSMClient = MANAGEMENT_ACCOUNT_SESSION.client("ssm")
except Exception as error:
LOGGER.error({"Unexpected_Error": error})
raise ValueError("Unexpected error executing Lambda function. Review CloudWatch logs for details.") from None
@@ -92,30 +94,14 @@ def assume_role(role: str, role_session_name: str, account: str = None, session:
def get_control_tower_regions() -> list: # noqa: CCR001
- """Query 'AWSControlTowerBP-BASELINE-CLOUDWATCH' CloudFormation stack to identify customer regions.
+ """Query ssm to identify customer regions.
Returns:
Customer regions chosen in Control Tower
"""
- paginator = CFN_CLIENT.get_paginator("list_stack_instances")
- customer_regions = set()
- aws_account = ""
- all_regions_identified = False
- for page in paginator.paginate(StackSetName="AWSControlTowerBP-BASELINE-CLOUDWATCH", PaginationConfig={"PageSize": CLOUDFORMATION_PAGE_SIZE}):
- for instance in page["Summaries"]:
- if not aws_account:
- aws_account = instance["Account"]
- customer_regions.add(instance["Region"])
- continue
- if aws_account == instance["Account"]:
- customer_regions.add(instance["Region"])
- continue
- all_regions_identified = True
- break
- if all_regions_identified:
- break
- sleep(CLOUDFORMATION_THROTTLE_PERIOD)
-
+ customer_regions = []
+ ssm_response = SSM_CLIENT.get_parameter(Name="/sra/regions/customer-control-tower-regions")
+ customer_regions = ssm_response["Parameter"]["Value"].split(",")
return list(customer_regions)
@@ -332,7 +318,6 @@ def process_accounts(event: Union[CloudFormationCustomResourceEvent, dict], para
sns_messages = []
accounts = get_active_organization_accounts()
for account in accounts:
-
if is_account_with_exclude_tags(account, params):
continue
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-global-events.yaml b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-global-events.yaml
index aeadb87d..0353cd57 100644
--- a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-global-events.yaml
+++ b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-global-events.yaml
@@ -53,7 +53,7 @@ Resources:
source:
- aws.organizations
detail-type:
- - AWS API Call via CloudTrail
+ - AWS Service Event via CloudTrail
detail:
eventSource:
- organizations.amazonaws.com
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main-ssm.yaml b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main-ssm.yaml
index 725ee6b5..d0b3bbfb 100644
--- a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main-ssm.yaml
+++ b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main-ssm.yaml
@@ -23,6 +23,12 @@ Metadata:
- pRootOrganizationalUnitId
- pSRAAlarmEmail
+ - Label:
+ default: IAM Properties
+ Parameters:
+ - pStackSetAdminRole
+ - pStackExecutionRole
+
- Label:
default: EC2 Default EBS Encryption Properties
Parameters:
@@ -45,6 +51,10 @@ Metadata:
- pComplianceFrequency
ParameterLabels:
+ pStackSetAdminRole:
+ default: Stack Set Role
+ pStackExecutionRole:
+ default: Stack execution role
pComplianceFrequency:
default: Frequency to Check for Organizational Compliance
pControlTowerRegionsOnly:
@@ -75,6 +85,16 @@ Metadata:
default: SRA Staging S3 Bucket Name
Parameters:
+ pStackSetAdminRole:
+ AllowedValues: [sra-stackset]
+ Default: sra-stackset
+ Description: The administration role name that is used in the stackset.
+ Type: String
+ pStackExecutionRole:
+ AllowedValues: [sra-execution]
+ Default: sra-execution
+ Description: The execution role name that is used in the stack.
+ Type: String
pComplianceFrequency:
ConstraintDescription: Compliance Frequency must be a number between 1 and 30, inclusive.
Default: 7
@@ -256,13 +276,13 @@ Resources:
DependsOn: rEC2DefaultEBSEncryptionStack
Properties:
StackSetName: sra-ec2-default-ebs-encryption-global-events
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Capabilities:
- CAPABILITY_NAMED_IAM
Description:
!Sub ${pSRASolutionVersion} - Deploys EventBridge Rules via ${pSRASolutionName} for capturing global events forwarding to the home region.
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main.yaml b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main.yaml
index 65a4b21e..1d8ea4e9 100644
--- a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main.yaml
+++ b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption-main.yaml
@@ -23,6 +23,12 @@ Metadata:
- pRootOrganizationalUnitId
- pSRAAlarmEmail
+ - Label:
+ default: IAM Properties
+ Parameters:
+ - pStackSetAdminRole
+ - pStackExecutionRole
+
- Label:
default: EC2 Default EBS Encryption Properties
Parameters:
@@ -45,6 +51,10 @@ Metadata:
- pComplianceFrequency
ParameterLabels:
+ pStackSetAdminRole:
+ default: Stack Set Role
+ pStackExecutionRole:
+ default: Stack execution role
pComplianceFrequency:
default: Frequency to Check for Organizational Compliance
pControlTowerRegionsOnly:
@@ -75,6 +85,16 @@ Metadata:
default: SRA Staging S3 Bucket Name
Parameters:
+ pStackSetAdminRole:
+ AllowedValues: [sra-stackset]
+ Default: sra-stackset
+ Description: The administration role name that is used in the stackset.
+ Type: String
+ pStackExecutionRole:
+ AllowedValues: [sra-execution]
+ Default: sra-execution
+ Description: The execution role name that is used in the stack.
+ Type: String
pComplianceFrequency:
ConstraintDescription: Compliance Frequency must be a number between 1 and 30, inclusive.
Default: 7
@@ -251,13 +271,13 @@ Resources:
DependsOn: rEC2DefaultEBSEncryptionStack
Properties:
StackSetName: sra-ec2-default-ebs-encryption-global-events
- AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSControlTowerStackSetRole
+ AdministrationRoleARN: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${pStackSetAdminRole}
CallAs: SELF
Capabilities:
- CAPABILITY_NAMED_IAM
Description:
!Sub ${pSRASolutionVersion} - Deploys EventBridge Rules via ${pSRASolutionName} for capturing global events forwarding to the home region.
- ExecutionRoleName: AWSControlTowerExecution
+ ExecutionRoleName: !Ref pStackExecutionRole
ManagedExecution:
Active: true
OperationPreferences:
diff --git a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption.yaml b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption.yaml
index 79d98390..72f49be6 100644
--- a/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption.yaml
+++ b/aws_sra_examples/solutions/ec2/ec2_default_ebs_encryption/templates/sra-ec2-default-ebs-encryption.yaml
@@ -326,6 +326,17 @@ Resources:
Action: cloudformation:ListStackInstances
Resource: !Sub arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stackset/AWSControlTowerBP-*
+ - PolicyName: "ssm-access"
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - ssm:GetParameter
+ - ssm:GetParameters
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/sra*"
+
- PolicyName: sra-ec2-default-ebs-encryption-policy-iam
PolicyDocument:
Version: 2012-10-17
@@ -483,7 +494,7 @@ Resources:
source:
- aws.organizations
detail-type:
- - AWS API Call via CloudTrail
+ - AWS Service Event via CloudTrail
detail:
eventSource:
- organizations.amazonaws.com
diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml
index 68d44d5f..80bd3df7 100644
--- a/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml
+++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml
@@ -610,4 +610,15 @@ Resources:
AlarmActions:
- !Ref rGuardDutyOrgDLQAlarmTopic
InsufficientDataActions:
- - !Ref rGuardDutyOrgDLQAlarmTopic
\ No newline at end of file
+ - !Ref rGuardDutyOrgDLQAlarmTopic
+
+Outputs:
+ oPublishingDestinationBucketName:
+ Description: Publishing Destination Bucket Name
+ Value: !Ref pPublishingDestinationBucketName
+ oPublishingDestinationBucketArn:
+ Description: Publishing Destination Bucket Name
+ Value: !Sub arn:${AWS::Partition}:s3:::${pPublishingDestinationBucketName}
+ oGuardDutyDeliveryKeyArn:
+ Description: GuardDuty Delivery KMS Key ARN
+ Value: !Ref pKMSKeyArn
\ No newline at end of file
diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml
index 9252d23a..aa5f65f3 100644
--- a/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml
+++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml
@@ -170,3 +170,5 @@ Outputs:
oGuardDutyDeliveryKeyArn:
Description: GuardDuty Delivery KMS Key ARN
Value: !GetAtt rGuardDutyDeliveryKey.Arn
+ # Export:
+ # Name: eGuardDutyDeliveryKeyArn
diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-main-ssm.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-main-ssm.yaml
index df3e8b73..37e57f47 100644
--- a/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-main-ssm.yaml
+++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-main-ssm.yaml
@@ -457,3 +457,20 @@ Resources:
Tags:
- Key: sra-solution
Value: !Ref pSRASolutionName
+
+Outputs:
+ oPublishingDestinationBucketName:
+ Description: Publishing Destination Bucket Name
+ Value: !GetAtt [rGuardDutyConfigurationStack, Outputs.oPublishingDestinationBucketName]
+ Export:
+ Name: ePublishingDestinationBucketName
+ oPublishingDestinationBucketArn:
+ Description: Publishing Destination Bucket Name
+ Value: !GetAtt [rGuardDutyConfigurationStack, Outputs.oPublishingDestinationBucketArn]
+ Export:
+ Name: ePublishingDestinationBucketArn
+ oGuardDutyDeliveryKeyArn:
+ Description: GuardDuty Delivery KMS Key ARN
+ Value: !GetAtt [rGuardDutyConfigurationStack, Outputs.oGuardDutyDeliveryKeyArn]
+ Export:
+ Name: eGuardDutyDeliveryKeyArn
diff --git a/aws_sra_examples/solutions/iam/iam_password_policy/lambda/src/app.py b/aws_sra_examples/solutions/iam/iam_password_policy/lambda/src/app.py
index abd2fff7..9c1ca976 100644
--- a/aws_sra_examples/solutions/iam/iam_password_policy/lambda/src/app.py
+++ b/aws_sra_examples/solutions/iam/iam_password_policy/lambda/src/app.py
@@ -86,7 +86,9 @@ def get_validated_parameters(event: CloudFormationCustomResourceEvent) -> dict:
true_false_pattern = r"^true|false$"
- parameter_pattern_validator("MAX_PASSWORD_AGE", params.get("MAX_PASSWORD_AGE", ""), pattern=r"^[0-9]$|^[0-9][0-9]$|^[0-9][0-2][0-8]$")
+ parameter_pattern_validator(
+ "MAX_PASSWORD_AGE", params.get("MAX_PASSWORD_AGE", ""), pattern=r"^[1-9]$|^[0-9][0-9]$|^[0-9][0-9][0-9]$|^[0-1][0]([0-8][0-9]|[9][0-5])$"
+ )
parameter_pattern_validator(
"MINIMUM_PASSWORD_LENGTH", params.get("MINIMUM_PASSWORD_LENGTH", ""), pattern=r"^[6-9]$|^[0-9][0-9]$|^[0-9][0-2][0-8]$"
)
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/README.md b/aws_sra_examples/solutions/inspector/inspector_org/README.md
index 1107b218..b963c8f0 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/README.md
+++ b/aws_sra_examples/solutions/inspector/inspector_org/README.md
@@ -85,7 +85,7 @@ The Inspector Organization solution will automate enabling Amazon Inspector by d
#### 1.10 Inspector
- The Inspector delegated administrator is registered within organizations in the `management account` using the Inspector APIs within each provided region.
-- EC2, ECR, and Lambda function scanning is set to be auto-enabled for all associated member accounts (newly associated and newly created accounts)
+- EC2, ECR, Lambda standard and Lambda code scanning is set to be auto-enabled for all associated member accounts (newly associated and newly created accounts)
#### 1.11 Lambda Layer
@@ -112,7 +112,7 @@ populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-B
#### 2.3 Inspector (Delegated admin)
- Inspector is enabled in the delegated admin account within each provided region.
-- EC2, ECR, and Lambda function scanning is enabled.
+- EC2, ECR, Lambda standard and Lambda code scanning is enabled.
---
@@ -129,7 +129,7 @@ populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-B
#### 3.3 Inspector (Members)
- Inspector is enabled from the delegated administrator account.
-- EC2, ECR, and Lambda function scanning is enabled.
+- EC2, ECR, Lambda standard and Lambda code scanning is enabled.
---
@@ -171,9 +171,9 @@ In the `management account (home region)`, launch an AWS CloudFormation **Stack*
1. Verify that the delegated admin account is set for each region
2. Log into the Audit account and navigate to the Inspector page
1. Verify the Inspector service is enabled in each region
- 2. Verify the auto-enable ec2, ecr, and lambda scanning for new accounts is ON in each region
- 3. Verify all existing member accounts have inspector ec2, ecr, and lambda scanning enabled in each region
-3. Log into a member account and verify the inspector is enabled and configured to scan ec2, ecr, and lambda functions
+ 2. Verify the auto-enable ec2, ecr and lambda standard scanning for new accounts is ON in each region, and lambda code scanning in supported regions
+ 3. Verify all existing member accounts have inspector ec2, ecr, and lambda standard scanning enabled in each region, and lambda code scanning in supported regions
+3. Log into a member account and verify the inspector is enabled and configured to scan ec2, ecr, lambda functions and lambda code
#### Solution Update Instructions
@@ -205,3 +205,4 @@ In the `management account (home region)`, launch an AWS CloudFormation **Stack*
- [Managing AWS SDKs in Lambda Functions](https://docs.aws.amazon.com/lambda/latest/operatorguide/sdks-functions.html)
- [Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)
- [Python Boto3 SDK changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
+- [AWS Regions where Lambda code scanning is currently available](https://docs.aws.amazon.com/inspector/latest/user/inspector_regions.html)
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/manifest-v2.yaml b/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/manifest-v2.yaml
index f4cb49d5..dee25919 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/manifest-v2.yaml
+++ b/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/manifest-v2.yaml
@@ -30,7 +30,7 @@ resources:
- parameter_key: pSRASolutionVersion
parameter_value: 'v1.0'
- parameter_key: pScanComponents
- parameter_value: EC2, ECR, LAMBDA
+ parameter_value: EC2, ECR, LAMBDA, LAMBDA_CODE
- parameter_key: pEcrRescanDuration
parameter_value: 'LIFETIME'
deploy_method: stack_set
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main-ssm.json b/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main-ssm.json
index 9936812f..120034dd 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main-ssm.json
+++ b/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main-ssm.json
@@ -37,7 +37,7 @@
},
{
"ParameterKey": "pScanComponents",
- "ParameterValue": "EC2, ECR, LAMBDA"
+ "ParameterValue": "EC2, ECR, LAMBDA, LAMBDA_CODE"
},
{
"ParameterKey": "pEcrRescanDuration",
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main.json b/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main.json
index 2ed05a30..208d10da 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main.json
+++ b/aws_sra_examples/solutions/inspector/inspector_org/customizations_for_aws_control_tower/parameters/sra-inspector-org-main.json
@@ -53,7 +53,7 @@
},
{
"ParameterKey": "pScanComponents",
- "ParameterValue": "EC2, ECR, LAMBDA"
+ "ParameterValue": "EC2, ECR, LAMBDA, LAMBDA_CODE"
},
{
"ParameterKey": "pEcrRescanDuration",
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/app.py b/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/app.py
index 64680bc3..30fa87c9 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/app.py
+++ b/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/app.py
@@ -36,7 +36,7 @@
UNEXPECTED = "Unexpected!"
SERVICE_NAME = "inspector2.amazonaws.com"
SNS_PUBLISH_BATCH_MAX = 10
-ALL_INSPECTOR_SCAN_COMPONENTS = ["EC2", "ECR", "LAMBDA"]
+ALL_INSPECTOR_SCAN_COMPONENTS = ["EC2", "ECR", "LAMBDA", "LAMBDA_CODE"]
helper = CfnResource(json_logging=True, log_level=log_level, boto_level="CRITICAL", sleep_on_delete=120)
@@ -172,7 +172,9 @@ def get_validated_parameters(event: Dict[str, Any]) -> dict:
params.update(parameter_pattern_validator("SNS_TOPIC_ARN", os.environ.get("SNS_TOPIC_ARN"), pattern=sns_topic_pattern))
params.update(
parameter_pattern_validator(
- "SCAN_COMPONENTS", os.environ.get("SCAN_COMPONENTS"), pattern=r"(?i)^((ec2|ecr|lambda),?){0,2}(ec2|ecr|lambda){1}$"
+ "SCAN_COMPONENTS",
+ os.environ.get("SCAN_COMPONENTS"),
+ pattern=r"(?i)^((ec2|ecr|lambda|lambda_code),?){0,3}(ec2|ecr|lambda|lambda_code){1}$",
)
)
params.update(parameter_pattern_validator("ECR_SCAN_DURATION", os.environ.get("ECR_SCAN_DURATION"), pattern=r"^(LIFETIME|DAYS_30|DAYS_180){1}$"))
@@ -374,22 +376,17 @@ def setup_inspector_in_region(
scan_components: list of components to scan
ecr_scan_duration: ecr scan duration
"""
- scan_component_dict: AutoEnableTypeDef = {"ec2": False, "ecr": False, "lambda": False}
+ scan_component_dict: AutoEnableTypeDef = {"ec2": False, "ecr": False, "lambda": False, "lambdaCode": False}
for scan_component in scan_components:
- if scan_component.lower() == "ec2":
- scan_component_dict["ec2"] = True
- elif scan_component.lower() == "ecr":
- scan_component_dict["ecr"] = True
- elif scan_component.lower() == "lambda":
- scan_component_dict["lambda"] = True
+ scan_component_dict[common.snake_to_camel(scan_component)] = True # type: ignore
+
+ if scan_component_dict["lambdaCode"] and not scan_component_dict["lambda"]:
+ scan_component_dict["lambda"] = True
disabled_components: list = []
- if scan_component_dict["ec2"] is False:
- disabled_components.append("ec2")
- if scan_component_dict["ecr"] is False:
- disabled_components.append("ecr")
- if scan_component_dict["lambda"] is False:
- disabled_components.append("lambda")
+ for scan_component in scan_component_dict:
+ if scan_component_dict[scan_component] is False: # type: ignore
+ disabled_components.append(scan_component)
LOGGER.info(f"setup_inspector_in_region: scan_components - ({scan_components}) in {region}")
LOGGER.info(f"setup_inspector_in_region: created scan_component_dict as ({scan_component_dict})")
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/common.py b/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/common.py
index cbc2d4c2..dbb3ad3b 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/common.py
+++ b/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/common.py
@@ -206,3 +206,30 @@ def create_service_linked_role(
LOGGER.info(api_call_details)
except iam_client.exceptions.NoSuchEntityException:
iam_client.create_service_linked_role(AWSServiceName=service_name, Description=description)
+
+
+def snake_to_camel(snake_str: str) -> str:
+ """Convert snake case to camel case.
+
+ Args:
+ snake_str: String to convert
+
+ Returns:
+ Camel case string
+ """
+ camel_str = snake_str.title().replace("_", "")
+ return camel_str[0].lower() + camel_str[1:]
+
+
+def camel_to_snake_upper(camel_str: str) -> str:
+ """Concert camel case to snake upper case.
+
+ Args:
+ camel_str: String to convert
+
+ Returns:
+ Snake upper case string
+ """
+ snake_chars = ["_" + x.lower() if x.isupper() else x for x in camel_str]
+ snake_str = "".join(snake_chars).lstrip("_")
+ return snake_str.upper()
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/inspector.py b/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/inspector.py
index 91a51a26..3bd16520 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/inspector.py
+++ b/aws_sra_examples/solutions/inspector/inspector_org/lambda/src/inspector.py
@@ -246,6 +246,7 @@ def check_inspector_org_auto_enabled(inspector2_delegated_admin_client: Inspecto
org_config_ec2_auto_enabled = 0
org_config_ecr_auto_enabled = 0
org_config_lambda_auto_enabled = 0
+ org_config_lambda_code_auto_enabled = 0
if "ec2" in describe_org_conf_response["autoEnable"] and describe_org_conf_response["autoEnable"]["ec2"] is True:
org_config_ec2_auto_enabled = 1
LOGGER.info("Organization inspector scanning for ec2 is already configured to be auto-enabled")
@@ -255,11 +256,14 @@ def check_inspector_org_auto_enabled(inspector2_delegated_admin_client: Inspecto
if "lambda" in describe_org_conf_response["autoEnable"] and describe_org_conf_response["autoEnable"]["lambda"] is True:
org_config_lambda_auto_enabled = 1
LOGGER.info("Organization inspector scanning for lambda is already configured to be auto-enabled")
- return org_config_ec2_auto_enabled + org_config_ecr_auto_enabled + org_config_lambda_auto_enabled
+ if "lambdaCode" in describe_org_conf_response["autoEnable"] and describe_org_conf_response["autoEnable"]["lambdaCode"] is True:
+ org_config_lambda_code_auto_enabled = 1
+ LOGGER.info("Organization inspector scanning for lambda code is already configured to be auto-enabled")
+ return org_config_ec2_auto_enabled + org_config_ecr_auto_enabled + org_config_lambda_auto_enabled + org_config_lambda_code_auto_enabled
def disable_auto_scanning_in_org(delegated_admin_account_id: str, configuration_role_name: str, regions: list) -> None:
- """Disable auto-enable setting in org for ec2, ec2, and lambda.
+ """Disable auto-enable setting in org for ec2, ec2, lambda and lambdaCode.
Args:
regions: AWS Region List
@@ -273,7 +277,7 @@ def disable_auto_scanning_in_org(delegated_admin_account_id: str, configuration_
if check_inspector_org_auto_enabled(inspector_delegated_admin_region_client) > 0:
LOGGER.info(f"disabling inspector scanning auto-enable in region {region}")
update_organization_configuration_response = inspector_delegated_admin_region_client.update_organization_configuration(
- autoEnable={"ec2": False, "ecr": False, "lambda": False}
+ autoEnable={"ec2": False, "ecr": False, "lambda": False, "lambdaCode": False}
)
api_call_details = {"API_Call": "inspector:UpdateOrganizationConfiguration", "API_Response": update_organization_configuration_response}
LOGGER.info(api_call_details)
@@ -301,8 +305,8 @@ def get_inspector_status(inspector2_client: Inspector2Client, account_id: str, s
if status["state"]["status"] == "ENABLED":
LOGGER.info(f"Status: {status['state']['status']}")
for scan_component in scan_components:
- LOGGER.info(f"{scan_component} status: {status['resourceState'][scan_component.lower()]['status']}") # type: ignore
- if status["resourceState"][scan_component.lower()]["status"] != "ENABLED": # type: ignore
+ LOGGER.info(f"{scan_component} status: {status['resourceState'][common.snake_to_camel(scan_component)]['status']}") # type: ignore
+ if status["resourceState"][common.snake_to_camel(scan_component)]["status"] != "ENABLED": # type: ignore
LOGGER.info(f"{scan_component} scan component is disabled...")
else:
LOGGER.info(f"{scan_component} scan component is enabled...")
@@ -358,15 +362,17 @@ def check_for_updates_to_scan_components(inspector2_client: Inspector2Client, ac
if status["state"]["status"] == "ENABLED":
LOGGER.info(f"Status: {status['state']['status']}")
for scan_component in disabled_components:
- LOGGER.info(f"{scan_component} status: {status['resourceState'][scan_component.lower()]['status']}") # type: ignore
- if status["resourceState"][scan_component.lower()]["status"] != "ENABLED": # type: ignore
+ LOGGER.info(f"{scan_component} status: {status['resourceState'][scan_component]['status']}") # type: ignore
+ if status["resourceState"][scan_component]["status"] != "ENABLED": # type: ignore
LOGGER.info(f"{scan_component} scan component is disabled...")
else:
LOGGER.info(f"{scan_component} scan component is enabled (disablement required)...")
disablement = True
if disablement is True:
LOGGER.info("Disabling some scan components...")
- disable_inspector2(inspector2_client, account_id, [disabled_component.upper() for disabled_component in disabled_components])
+ disable_inspector2(
+ inspector2_client, account_id, [common.camel_to_snake_upper(disabled_component) for disabled_component in disabled_components]
+ )
def enable_inspector2_in_mgmt_and_delegated_admin(
@@ -490,12 +496,9 @@ def set_auto_enable_inspector_in_org(
scan_component_dict: dictionary of scan components with true/false enable value
"""
enabled_component_count: int = 0
- if scan_component_dict["ec2"] is True:
- enabled_component_count = enabled_component_count + 1
- if scan_component_dict["ecr"] is True:
- enabled_component_count = enabled_component_count + 1
- if scan_component_dict["lambda"] is True:
- enabled_component_count = enabled_component_count + 1
+ for scan_component in scan_component_dict:
+ if scan_component_dict[scan_component] is True: # type: ignore
+ enabled_component_count = enabled_component_count + 1
LOGGER.info(f"set_auto_enable_inspector_in_org: scan_component_dict - ({scan_component_dict})")
delegated_admin_session = common.assume_role(configuration_role_name, "sra-enable-inspector", delegated_admin_account_id)
@@ -503,7 +506,7 @@ def set_auto_enable_inspector_in_org(
inspector_delegated_admin_region_client: Inspector2Client = delegated_admin_session.client("inspector2", region)
if check_inspector_org_auto_enabled(inspector_delegated_admin_region_client) != enabled_component_count:
- LOGGER.info(f"configuring aut-enable inspector via update_organization_configuration in region {region}")
+ LOGGER.info(f"configuring auto-enable inspector via update_organization_configuration in region {region}")
update_organization_configuration_response = inspector_delegated_admin_region_client.update_organization_configuration(
autoEnable=scan_component_dict
)
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-configuration.yaml b/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-configuration.yaml
index 3a83ed50..dbd17300 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-configuration.yaml
+++ b/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-configuration.yaml
@@ -88,7 +88,7 @@ Metadata:
pInspectorConfigurationRoleName:
default: Inspector Configuration Role Name
pScanComponents:
- default: Comma separated list of scan components (EC2, ECR, LAMBDA)
+ default: Comma separated list of scan components (EC2, ECR, LAMBDA, LAMBDA_CODE)
pEcrRescanDuration:
default: ECR Rescan Duration
@@ -195,8 +195,8 @@ Parameters:
numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
Type: String
pScanComponents:
- AllowedValues: [EC2, ECR, LAMBDA]
- Default: EC2, ECR, LAMBDA
+ AllowedValues: [EC2, ECR, LAMBDA, LAMBDA_CODE]
+ Default: EC2, ECR, LAMBDA, LAMBDA_CODE
Description: Lambda Function Logging Level
Type: CommaDelimitedList
pEcrRescanDuration:
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main-ssm.yaml b/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main-ssm.yaml
index a4e60dbf..edcb6762 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main-ssm.yaml
+++ b/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main-ssm.yaml
@@ -89,7 +89,7 @@ Metadata:
pSRAStagingS3BucketName:
default: SRA Staging S3 Bucket Name
pScanComponents:
- default: Comma separated list of scan components (EC2, ECR, LAMBDA)
+ default: Comma separated list of scan components (EC2, ECR, LAMBDA, LAMBDA_CODE)
pEcrRescanDuration:
default: ECR Rescan Duration
@@ -202,8 +202,8 @@ Parameters:
Description: The SRA solution version. Used to trigger updates on the nested StackSets.
Type: String
pScanComponents:
- AllowedValues: [EC2, ECR, LAMBDA]
- Default: EC2, ECR, LAMBDA
+ AllowedValues: [EC2, ECR, LAMBDA, LAMBDA_CODE]
+ Default: EC2, ECR, LAMBDA, LAMBDA_CODE
Description: Lambda Function Logging Level
Type: CommaDelimitedList
pEcrRescanDuration:
diff --git a/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main.yaml b/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main.yaml
index 48774890..fa809463 100644
--- a/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main.yaml
+++ b/aws_sra_examples/solutions/inspector/inspector_org/templates/sra-inspector-org-main.yaml
@@ -92,7 +92,7 @@ Metadata:
pSRASolutionVersion:
default: SRA Solution Version
pScanComponents:
- default: Comma separated list of scan components (EC2, ECR, LAMBDA)
+ default: Comma separated list of scan components (EC2, ECR, LAMBDA, LAMBDA_CODE)
pEcrRescanDuration:
default: ECR Rescan Duration
@@ -200,8 +200,8 @@ Parameters:
Description: The SRA solution version. Used to trigger updates on the nested StackSets.
Type: String
pScanComponents:
- AllowedValues: [EC2, ECR, LAMBDA]
- Default: EC2, ECR, LAMBDA
+ AllowedValues: [EC2, ECR, LAMBDA, LAMBDA_CODE]
+ Default: EC2, ECR, LAMBDA, LAMBDA_CODE
Description: Lambda Function Logging Level
Type: CommaDelimitedList
pEcrRescanDuration:
diff --git a/aws_sra_examples/solutions/macie/macie_org/README.md b/aws_sra_examples/solutions/macie/macie_org/README.md
index fe298907..aa51dd26 100644
--- a/aws_sra_examples/solutions/macie/macie_org/README.md
+++ b/aws_sra_examples/solutions/macie/macie_org/README.md
@@ -74,7 +74,7 @@ The Lambda function is required to register the Macie delegated administrator ac
#### 2.3 Macie
-- See [1.5 Macie](#15-macie)
+- See [1.8 Macie](#18-macie)
---
@@ -96,7 +96,7 @@ The example solutions use `Audit Account` instead of `Security Tooling Account`
#### 3.4 Macie
-- See [1.5 Macie](#15-macie)
+- See [1.8 Macie](#18-macie)
---
@@ -104,7 +104,7 @@ The example solutions use `Audit Account` instead of `Security Tooling Account`
#### 4.1 Macie
-- See [1.5 Macie](#15-macie)
+- See [1.8 Macie](#18-macie)
#### 4.2 Disable Macie Role