AWSTemplateFormatVersion: "2010-09-09" Description: "AWS CloudFormation template which contains the resources for synthetic tests demo." Parameters: DemoResourcesS3BucketName: Description: Amazon S3 bucket where demo resources zip file was uploaded to. Type: String DemoResourcesS3ObjectKey: Description: Amazon S3 object key with which demo resources zip file was uploaded to. Type: String CodeDeploySampleAppS3BucketName: Description: Amazon S3 bucket which contains AWS CodeDeploy sample app. Type: String CodeDeploySampleAppS3ObjectKey: Description: Amazon S3 object key of AWS CodeDeploy sample app. Type: String TimeWindowConfiguration: Description: JSON object which contains time windows configuration. Type: String KeyPairName: Description: The name of an existing Amazon EC2 key pair to enable SSH or RDP access. to the instances. Type: String MinLength: '1' MaxLength: '255' AllowedPattern: "[\\x20-\\x7E]*" ConstraintDescription: Can contain only ASCII characters. YourIP: Description: "IP address to connect to SSH from. Check http://checkip.amazonaws.com/ to find yours." Type: String Default: "0.0.0.0/0" Mappings: RegionOS2AMI: us-east-1: Linux: ami-7c807d14 us-west-2: Linux: ami-1b3b462b eu-west-1: Linux: ami-672ce210 ap-southeast-2: Linux: ami-6bf99c51 ap-southeast-1: Linux: ami-c9b572aa us-west-1: Linux: ami-d5ea86b5 eu-central-1: Linux: ami-ae221fb3 ap-northeast-1: Linux: ami-25dd9324 sa-east-1: Linux: ami-d412aab8 Resources: # The instance will use this role to access S3 EC2Role: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Statement: - Sid: "" Effect: "Allow" Principal: Service: - "ec2.amazonaws.com" Action: "sts:AssumeRole" Policies: - PolicyName: "s3" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "s3:GetObject" Resource: - "Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "ArtifactStoreBucket"}, "/*" ]] - "Fn::Join": ["", ["arn:aws:s3:::aws-codedeploy-", {"Ref": "AWS::Region"}, "/*" ]] EC2InstanceProfile: Type: "AWS::IAM::InstanceProfile" Properties: Roles: - Ref: "EC2Role" SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Enable HTTP access via port 80 and SSH access." SecurityGroupIngress: - IpProtocol: tcp FromPort: "80" ToPort: "80" CidrIp: "0.0.0.0/0" - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref YourIP LaunchConfiguration: Type: "AWS::AutoScaling::LaunchConfiguration" Properties: IamInstanceProfile: {"Ref": "EC2InstanceProfile"} ImageId: { "Fn::FindInMap": ["RegionOS2AMI", { "Ref" : "AWS::Region" } , "Linux"]} InstanceType: t1.micro KeyName: !Ref KeyPairName SecurityGroups: - {"Ref": "SecurityGroup"} UserData: "Fn::Base64": "Fn::Join": - "" - [ "#!/bin/bash -xe\n", "/usr/bin/yum -y update\n", "/usr/bin/yum install -y ruby\n", "/usr/bin/yum install -y aws-cli\n", "cd /home/ec2-user/\n", "/usr/bin/aws s3 cp s3://aws-codedeploy-", { "Ref" : "AWS::Region" }, "/latest/install . --region ", { "Ref" : "AWS::Region" }, "\n", "/bin/chmod +x ./install\n", "./install auto\n" ] CodeDeployTrustRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Statement: - Sid: "" Effect: "Allow" Principal: Service: - "codedeploy.amazonaws.com" Action: "sts:AssumeRole" ManagedPolicyArns: - "arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole" Path: "/" CodeDeployApplication: Type: "AWS::CodeDeploy::Application" # Autoscaling groups AutoscalingGroup: Type: "AWS::AutoScaling::AutoScalingGroup" Properties: AvailabilityZones: { "Fn::GetAZs" : { "Ref" : "AWS::Region" } } DesiredCapacity: 1 LaunchConfigurationName: {"Ref": "LaunchConfiguration"} MinSize: "1" MaxSize: "3" CodeDeployDeploymentGroup: Type: "AWS::CodeDeploy::DeploymentGroup" Properties: ApplicationName: {"Ref": "CodeDeployApplication"} ServiceRoleArn: {"Fn::GetAtt" : ["CodeDeployTrustRole","Arn"]} AutoScalingGroups: - {"Ref": "AutoscalingGroup"} ArtifactStoreBucket: Type: AWS::S3::Bucket Pipeline: Type: AWS::CodePipeline::Pipeline Properties: ArtifactStore: Location: !Ref 'ArtifactStoreBucket' Type: S3 Name: "TimeWindowsDemoPipeline" RoleArn: !GetAtt [PipelineRole, Arn] Stages: - Name: Source Actions: - Name: S3Source ActionTypeId: Category: Source Owner: AWS Provider: S3 Version: '1' Configuration: S3Bucket: !Ref CodeDeploySampleAppS3BucketName S3ObjectKey: !Ref CodeDeploySampleAppS3ObjectKey OutputArtifacts: - Name: CodeDeployArtifacts RunOrder: '1' - Name: Deploy Actions: - Name: TimeWindowApproval ActionTypeId: Category: Approval Owner: AWS Provider: Manual Version: '1' Configuration: CustomData: !Ref TimeWindowConfiguration NotificationArn: !Ref PipelineApprovalSNSNotification RunOrder: '1' - Name: CodeDeployApp ActionTypeId: Category: Deploy Owner: AWS Provider: CodeDeploy Version: '1' InputArtifacts: - Name: CodeDeployArtifacts Configuration: ApplicationName: !Ref CodeDeployApplication DeploymentGroupName: !Ref CodeDeployDeploymentGroup RunOrder: '2' PipelineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: ['sts:AssumeRole'] Effect: Allow Principal: Service: [codepipeline.amazonaws.com] Version: '2012-10-17' Path: / Policies: - PolicyName: CodePipelineAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - "s3:GetObject" - "s3:GetObjectVersion" Resource: - "Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "CodeDeploySampleAppS3BucketName"}, "/*"]] - Effect: Allow Action: - "s3:GetBucketVersioning" Resource: - "Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "CodeDeploySampleAppS3BucketName"}]] - Effect: Allow Action: - "s3:GetObject" - "s3:PutObject" Resource: - "Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "ArtifactStoreBucket"}, "/*" ]] - Effect: "Allow" Action: - "s3:ListBucket" Resource: - "Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "ArtifactStoreBucket"}]] - Effect: Allow Action: - "codedeploy:CreateDeployment" - "codedeploy:GetApplicationRevision" - "codedeploy:GetDeployment" - "codedeploy:GetDeploymentConfig" - "codedeploy:RegisterApplicationRevision" Resource: "*" - Effect: Allow Action: - "sns:Publish" Resource: !Ref PipelineApprovalSNSNotification PipelineAppovalTable: Type: "AWS::DynamoDB::Table" Properties: AttributeDefinitions: - AttributeName: "ApprovalToken" AttributeType: "S" KeySchema: - AttributeName: "ApprovalToken" KeyType: "HASH" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "TimeWindowDemo-PipelineApprovals" RegisterTimeWindowLambdaFunctionExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: ['sts:AssumeRole'] Effect: Allow Principal: Service: [lambda.amazonaws.com] Version: '2012-10-17' Path: / Policies: - PolicyName: CodePipelineAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - "dynamodb:PutItem" Resource: - "Fn::Join": ["", ["arn:aws:dynamodb:", { "Ref" : "AWS::Region" }, ":", { "Ref" : "AWS::AccountId" }, ":table/", {"Ref": "PipelineAppovalTable"}]] - Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "arn:aws:logs:*:*:*" RegisterTimeWindowLambdaFunction: Type: AWS::Lambda::Function Properties: Handler: "register-time-window.handler" Role: !GetAtt [RegisterTimeWindowLambdaFunctionExecutionRole, Arn] Code: S3Bucket: !Ref DemoResourcesS3BucketName S3Key: !Ref DemoResourcesS3ObjectKey Runtime: nodejs4.3 Timeout: 25 RegisterTimeWindowInvokePermission: Type: AWS::Lambda::Permission Properties: FunctionName: { "Fn::GetAtt" : ["RegisterTimeWindowLambdaFunction", "Arn"]} Action: "lambda:InvokeFunction" Principal: "sns.amazonaws.com" SourceArn: !Ref PipelineApprovalSNSNotification PipelineApprovalSNSNotification: Type: AWS::SNS::Topic Properties: Subscription: - Protocol: "lambda" Endpoint: { "Fn::GetAtt" : ["RegisterTimeWindowLambdaFunction", "Arn"]} ProcessTimeWindowsFunctionExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: ['sts:AssumeRole'] Effect: Allow Principal: Service: [lambda.amazonaws.com] Version: '2012-10-17' Path: / Policies: - PolicyName: CloudWatchAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "arn:aws:logs:*:*:*" - Effect: Allow Action: - "codepipeline:PutApprovalResult" Resource: - "Fn::Join": ["", ["arn:aws:codepipeline:", { "Ref" : "AWS::Region" }, ":", { "Ref" : "AWS::AccountId" }, ":", {"Ref": "Pipeline"}, "/*"]] - Effect: Allow Action: - "dynamodb:Scan" - "dynamodb:DeleteItem" Resource: - "Fn::Join": ["", ["arn:aws:dynamodb:", { "Ref" : "AWS::Region" }, ":", { "Ref" : "AWS::AccountId" }, ":table/", {"Ref": "PipelineAppovalTable"}]] ProcessTimeWindowsLambdaFunction: Type: AWS::Lambda::Function Properties: Handler: "process-time-windows.handler" Role: !GetAtt [ProcessTimeWindowsFunctionExecutionRole, Arn] Code: S3Bucket: !Ref DemoResourcesS3BucketName S3Key: !Ref DemoResourcesS3ObjectKey Runtime: "nodejs4.3" Timeout: "25" ProcessTimeWindowsInvokePermission: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt [ProcessTimeWindowsLambdaFunction, Arn] Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: !GetAtt [ProcessTimeWindowsScheduleTrigger, Arn] ProcessTimeWindowsScheduleTrigger: Type: AWS::Events::Rule Properties: ScheduleExpression: rate(1 minute) State: ENABLED Targets: - Arn: !GetAtt [ProcessTimeWindowsLambdaFunction, Arn] Id: "InvokeProcessTimeWindows"