--- AWSTemplateFormatVersion: '2010-09-09' Description: CodePipeline for Config Rules, CloudWatch Event Rules, and Lambda Parameters: EmailAddress: Description: Email Address for sending SNS notifications for CodeCommit Type: String Default: fake-email@fake-fake-fake-email.com RepositoryBranch: Description: The name of the branch for the CodeCommit repo Type: String Default: main AllowedPattern: "[\\x20-\\x7E]*" ConstraintDescription: Can contain only ASCII characters. CodeCommitS3Bucket: Description: S3 bucket that holds zip of source code for CodeCommit Repo Type: String AllowedPattern: "^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" MaxLength: 63 CodeCommitS3Key: Description: zipfile key located in CodeCommitS3Bucket Type: String ConfigRuleName: Type: String Default: s3-bucket-public-write-prohibited Description: The name that you assign to the AWS Config rule. MinLength: '1' ConstraintDescription: This parameter is required. MaximumExecutionFrequency: Type: String Default: TwentyFour_Hours Description: The frequency that you want AWS Config to run evaluations for the rule. MinLength: '1' ConstraintDescription: This parameter is required. AllowedValues: - One_Hour - Three_Hours - Six_Hours - Twelve_Hours - TwentyFour_Hours CreateConfig: Description: Flag to Create a Config Recorder and Delivery Channel Default: create Type: String AllowedValues: - create - donotcreate ConstraintDescription: must specify create or donotcreate. Conditions: CreateNewConfigResources: !Equals [ !Ref CreateConfig, create ] Resources: ConfigBucket: Type: AWS::S3::Bucket Condition: CreateNewConfigResources DeletionPolicy: Retain UpdateReplacePolicy: Retain Properties: AccessControl: BucketOwnerFullControl ConfigTopic: Type: AWS::SNS::Topic Condition: CreateNewConfigResources DeliveryChannel: Type: AWS::Config::DeliveryChannel Condition: CreateNewConfigResources Properties: ConfigSnapshotDeliveryProperties: DeliveryFrequency: "Six_Hours" S3BucketName: Ref: ConfigBucket SnsTopicARN: Ref: ConfigTopic ConfigBucketPolicy: Type: AWS::S3::BucketPolicy Condition: CreateNewConfigResources Properties: Bucket: !Ref 'ConfigBucket' PolicyDocument: Version: '2012-10-17' Id: PutObjPolicy Statement: - Sid: DenyUnEncryptedObjects Effect: Deny Principal: '*' Action: s3:PutObject Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref 'ConfigBucket' - /* Condition: StringNotEquals: s3:x-amz-server-side-encryption: AES256 ConfigRole: Type: AWS::IAM::Role Condition: CreateNewConfigResources Properties: AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - config.amazonaws.com Version: '2012-10-17' Path: / Policies: - PolicyDocument: Statement: - Effect: Allow Action: sns:Publish Resource: !Ref 'ConfigTopic' - Effect: Allow Action: - s3:PutObject Resource: !Sub arn:aws:s3:::${ConfigBucket}/AWSLogs/${AWS::AccountId}/* Condition: StringLike: s3:x-amz-acl: bucket-owner-full-control - Effect: Allow Action: - s3:GetBucketAcl Resource: !Sub arn:aws:s3:::${ConfigBucket} PolicyName: root ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSConfigRole ConfigRecorder: Type: AWS::Config::ConfigurationRecorder Condition: CreateNewConfigResources Properties: RecordingGroup: AllSupported: true IncludeGlobalResourceTypes: true RoleARN: !GetAtt 'ConfigRole.Arn' AWSConfigRule: Type: AWS::Config::ConfigRule Condition: CreateNewConfigResources DependsOn: ConfigRecorder Properties: ConfigRuleName: Ref: ConfigRuleName Description: Checks that your Amazon S3 buckets do not allow public write access. The rule checks the Block Public Access settings, the bucket policy, and the bucket access control list (ACL). InputParameters: {} Scope: ComplianceResourceTypes: - AWS::S3::Bucket Source: Owner: AWS SourceIdentifier: S3_BUCKET_PUBLIC_WRITE_PROHIBITED MaximumExecutionFrequency: Ref: MaximumExecutionFrequency ArtifactBucket: Type: AWS::S3::Bucket DeletionPolicy: Retain UpdateReplacePolicy: Retain MyLambdaTrustRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Path: "/" Policies: - PolicyDocument: Statement: - Action: - s3:DeleteBucketPolicy - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: "*" Version: '2012-10-17' PolicyName: MyLambdaWorkerPolicy Type: AWS::IAM::Role CodeBuildRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - codebuild.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: codebuild-service PolicyDocument: Statement: - Action: - logs:* - lambda:* - cloudwatch:* - codebuild:* - s3:* Effect: Allow Resource: "*" Version: '2012-10-17' CodeBuildLambdaTrigger: Type: AWS::CodeBuild::Project Properties: Description: Package SAM Artifacts ServiceRole: Fn::GetAtt: - CodeBuildRole - Arn Artifacts: Type: NO_ARTIFACTS Environment: EnvironmentVariables: - Name: S3_BUCKET Value: Ref: ArtifactBucket Type: LINUX_CONTAINER ComputeType: BUILD_GENERAL1_SMALL Image: "aws/codebuild/amazonlinux2-x86_64-standard:4.0" Source: BuildSpec: buildspec-lambda.yml Location: !Sub https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/${AWS::StackName}/ Type: CODECOMMIT TimeoutInMinutes: 10 Tags: - Key: Owner Value: MyCodeBuildProject MySNSTopic: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: Ref: EmailAddress Protocol: email CodeCommitRepo: Type: AWS::CodeCommit::Repository Properties: RepositoryName: Ref: AWS::StackName RepositoryDescription: CodeCommit Repository for Config Rule solution Code: S3: Bucket: !Ref CodeCommitS3Bucket Key: !Ref CodeCommitS3Key Triggers: - Name: MasterTrigger CustomData: Ref: AWS::StackName DestinationArn: Ref: MySNSTopic Events: - all CloudFormationTrustRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: - cloudformation.amazonaws.com Path: "/" Policies: - PolicyDocument: Statement: - Action: - s3:PutObject - s3:GetObject - s3:GetObjectVersion Effect: Allow Resource: - !Sub arn:aws:s3:::${ArtifactBucket} - !Sub arn:aws:s3:::${ArtifactBucket}/* - Action: - lambda:CreateFunction - lambda:DeleteFunction - lambda:AddPermission - lambda:UpdateFunction - lambda:UpdateFunctionCode - lambda:GetFunctionConfiguration - lambda:UpdateFunctionConfiguration - lambda:RemovePermission - lambda:TagResource - lambda:ListTags - lambda:UntagResource - lambda:InvokeFunction - sns:CreateTopic - sns:DeleteTopic - sns:ListTopics - sns:GetTopicAttributes - sns:SetTopicAttributes - s3:CreateBucket - s3:DeleteBucket - events:* Effect: Allow Resource: "*" - Action: - iam:PassRole Effect: Allow Resource: - Fn::GetAtt: - MyLambdaTrustRole - Arn - Action: - cloudformation:CreateChangeSet Effect: Allow Resource: - arn:aws:cloudformation:us-east-1:aws:transform/Serverless-2016-10-31 PolicyName: CloudFormationRolePolicy Type: AWS::IAM::Role CodePipelineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - codepipeline.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: codepipeline-service PolicyDocument: Statement: - Action: - s3:GetObject - s3:GetObjectVersion - s3:GetBucketVersioning Resource: "*" Effect: Allow - Action: - s3:PutObject Resource: - arn:aws:s3:::codepipeline* Effect: Allow - Action: - s3:GetObject - s3:GetObjectVersion - s3:GetBucketVersioning - s3:PutObject - iam:PassRole Resource: "*" Effect: Allow - Action: - codecommit:* - codebuild:* - cloudformation:* Resource: "*" Effect: Allow Version: '2012-10-17' CodeBuildCfnNag: Type: AWS::CodeBuild::Project Properties: Name: Ref: AWS::StackName Description: Build application ServiceRole: Fn::GetAtt: - CodeBuildRole - Arn Artifacts: Type: NO_ARTIFACTS Environment: Type: LINUX_CONTAINER ComputeType: BUILD_GENERAL1_SMALL Image: "aws/codebuild/amazonlinux2-x86_64-standard:4.0" Source: BuildSpec: buildspec.yml Location: !Sub https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/${AWS::StackName}/ Type: CODECOMMIT TimeoutInMinutes: 10 Tags: - Key: Owner Value: MyCodeBuildProject PipelineBucket: Type: AWS::S3::Bucket DeletionPolicy: Retain UpdateReplacePolicy: Retain Pipeline: Type: AWS::CodePipeline::Pipeline Properties: RoleArn: !GetAtt CodePipelineRole.Arn Stages: - Name: Source Actions: - InputArtifacts: [] Name: Source ActionTypeId: Category: Source Owner: AWS Version: '1' Provider: CodeCommit OutputArtifacts: - Name: MyApp Configuration: BranchName: Ref: RepositoryBranch RepositoryName: Ref: AWS::StackName RunOrder: 1 - Name: Build Actions: - InputArtifacts: - Name: MyApp Name: cfn_nag ActionTypeId: Category: Test Owner: AWS Version: '1' Provider: CodeBuild OutputArtifacts: [] Configuration: ProjectName: Ref: CodeBuildCfnNag RunOrder: 1 - InputArtifacts: - Name: MyApp Name: BuildLambdaFunctions ActionTypeId: Category: Build Owner: AWS Version: '1' Provider: CodeBuild OutputArtifacts: - Name: lambdatrigger-BuildArtifact Configuration: ProjectName: Ref: CodeBuildLambdaTrigger RunOrder: 1 - Name: Deploy Actions: - InputArtifacts: - Name: lambdatrigger-BuildArtifact Name: GenerateChangeSetLambdaFunction ActionTypeId: Category: Deploy Owner: AWS Version: '1' Provider: CloudFormation OutputArtifacts: [] Configuration: ActionMode: CHANGE_SET_REPLACE ChangeSetName: pipeline-changeset RoleArn: Fn::GetAtt: - CloudFormationTrustRole - Arn Capabilities: CAPABILITY_IAM StackName: !Sub ${AWS::StackName}-${AWS::Region} TemplatePath: lambdatrigger-BuildArtifact::template-export.json RunOrder: 1 - ActionTypeId: Category: Deploy Owner: AWS Provider: CloudFormation Version: '1' Configuration: ActionMode: CHANGE_SET_EXECUTE ChangeSetName: pipeline-changeset StackName: !Sub ${AWS::StackName}-${AWS::Region} InputArtifacts: [] Name: ExecuteChangeSetLambdaFunction OutputArtifacts: [] RunOrder: 2 ArtifactStore: Type: S3 Location: !Ref PipelineBucket Outputs: PipelineUrl: Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${Pipeline} Description: CodePipeline URL LambdaTrustRole: Description: IAM role for AWS Lambda used for passRole to Lambda functions. Export: Name: !Sub ${AWS::StackName}-${AWS::Region}-LambdaTrustRole Value: Fn::GetAtt: - MyLambdaTrustRole - Arn