--- AWSTemplateFormatVersion: '2010-09-09' Description: Cloud9 + QuickStart VPC (qs-1pb4pob92) (Please do not remove) May,29,2019 Metadata: LICENSE: Apache License, Version 2.0 AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Cloud9 configuration Parameters: - C9InstanceType - C9StopTime - C9Subnet - EBSVolumeSize - BootstrapScriptS3Uri - BootstrapArguments - OwnerArn - Label: default: AWS Quick Start configuration Parameters: - OutputBucketName - QSS3BucketName - QSS3KeyPrefix ParameterLabels: C9InstanceType: default: Cloud9 instance type C9StopTime: default: Stop time C9Subnet: default: Public subnet ID EBSVolumeSize: default: EBS volume size BootstrapScriptS3Uri: default: Bootstrap script S3 URI BootstrapArguments: default: Bootstrap script arguments OutputBucketName: default: Output S3 bucket name QSS3BucketName: default: Quick Start S3 bucket name QSS3KeyPrefix: default: Quick Start S3 key prefix Parameters: C9InstanceType: Description: The instance type of the new Amazon EC2 instance that AWS Cloud9 will launch for the development environment. Type: String Default: t2.micro AllowedValues: - t2.nano - t2.micro - t2.small - t2.medium - t2.large - t2.xlarge - t2.2xlarge - t3.nano - t3.micro - t3.small - t3.medium - t3.large - t3.xlarge - t3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m4.16xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge - m5.12xlarge - m5.16xlarge - m5.24xlarge - m5.metal - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5.12xlarge - c5.18xlarge - c5.24xlarge - c5.metal C9StopTime: Description: The number of minutes until the running instance is shut down after the environment has last been used. Type: Number Default: 30 C9Subnet: Description: The ID of the public subnet where your Cloud9 IDE will be installed. Type: String EBSVolumeSize: Description: The desired size (GB) of the Amazon EBS volume for your Cloud9 IDE. Type: Number Default: 100 BootstrapScriptS3Uri: Description: S3 URI to a shell script that will be executed on the Cloud9 instance. If left blank, no custom bootstrap will be run. Type: String Default: '' BootstrapArguments: Description: Arguments string to pass to the bootstrap script. Type: String Default: '' OutputBucketName: Description: 'OPTIONAL: Bucket name where the zip file output should be placed. If left blank, a bucket name will be automatically generated.' Type: String Default: '' QSS3BucketName: AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: S3 bucket name for the Quick Start assets. This string can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Type: String QSS3KeyPrefix: AllowedPattern: ^[0-9a-zA-Z-/.]*$ ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), dots(.) and forward slash (/). Default: quickstart-cloud9-ide/ Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), dots(.) and forward slash (/). Type: String OwnerArn: Description: The Amazon Resource Name (ARN) of the environment owner. This ARN can be the ARN of any AWS Identity and Access Management (IAM) principal. If this value is not specified, the ARN defaults to this stack's creator. Type: String Default: '' Conditions: UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] CreateZipsBucket: !Equals [!Ref 'OutputBucketName', ''] DoCustomBootstrap: !Not [!Equals [!Ref 'BootstrapScriptS3Uri', '']] DoOwnerArn: !Not [!Equals [!Ref 'OwnerArn', '']] Resources: LambdaZipsBucket: Condition: CreateZipsBucket Type: AWS::S3::Bucket Properties: {} Cloud9Env: Type: AWS::Cloud9::EnvironmentEC2 Properties: # Name: !Ref AWS::StackName Description: !Sub '${AWS::AccountId}-${AWS::Region}-${AWS::StackName}' AutomaticStopTimeMinutes: !Ref C9StopTime InstanceType: !Ref C9InstanceType SubnetId: !Ref C9Subnet OwnerArn: !If [ DoOwnerArn, !Ref OwnerArn, !Ref 'AWS::NoValue'] Cloud9Role: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore Path: / Policies: - PolicyName: get-bootstrap PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: s3:GetObject Resource: !Sub 'arn:aws:s3:::${QSS3BucketName}/${QSS3KeyPrefix}*' - PolicyName: describe-ec2 PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: [ 'ec2:DescribeInstances', 'ec2:DescribeVolumes', 'ec2:ModifyVolume', ] Resource: '*' Cloud9InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: [!Ref Cloud9Role] CopyZipsRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Path: / Policies: - PolicyName: lambda-copier PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: s3:GetObject Resource: !Sub - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}* - S3Bucket: !If [ UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName, ] - Effect: Allow Action: ['s3:PutObject', 's3:DeleteObject'] Resource: 'Fn::Sub': - 'arn:aws:s3:::${ZipsBucket}/${QSS3KeyPrefix}*' - ZipsBucket: !If [ CreateZipsBucket, Ref: LambdaZipsBucket, Ref: OutputBucketName, ] CopyZipsFunction: Type: AWS::Lambda::Function Properties: Description: Copies objects from a source S3 bucket to a destination Handler: index.handler Runtime: python3.6 Role: !GetAtt CopyZipsRole.Arn Timeout: 240 Code: ZipFile: | import json import logging import threading import boto3 import cfnresponse def copy_objects(source_bucket, dest_bucket, prefix, objects): s3 = boto3.client('s3') for o in objects: key = prefix + o copy_source = { 'Bucket': source_bucket, 'Key': key } print('copy_source: %s' % copy_source) print('dest_bucket = %s'%dest_bucket) print('key = %s' %key) s3.copy_object(CopySource=copy_source, Bucket=dest_bucket, Key=key) def delete_objects(bucket, prefix, objects): s3 = boto3.client('s3') objects = {'Objects': [{'Key': prefix + o} for o in objects]} s3.delete_objects(Bucket=bucket, Delete=objects) def timeout(event, context): logging.error('Execution is about to time out, sending failure response to CloudFormation') cfnresponse.send(event, context, cfnresponse.FAILED, {}, None) def handler(event, context): # make sure we send a failure to CloudFormation if the function # is going to timeout timer = threading.Timer((context.get_remaining_time_in_millis() / 1000.00) - 0.5, timeout, args=[event, context]) timer.start() print('Received event: %s' % json.dumps(event)) status = cfnresponse.SUCCESS try: source_bucket = event['ResourceProperties']['SourceBucket'] dest_bucket = event['ResourceProperties']['DestBucket'] prefix = event['ResourceProperties']['Prefix'] objects = event['ResourceProperties']['Objects'] if event['RequestType'] == 'Delete': delete_objects(dest_bucket, prefix, objects) else: copy_objects(source_bucket, dest_bucket, prefix, objects) except Exception as e: logging.error('Exception: %s' % e, exc_info=True) status = cfnresponse.FAILED finally: timer.cancel() cfnresponse.send(event, context, status, {}, None) CopyZips: Type: Custom::CopyZips Properties: ServiceToken: !GetAtt 'CopyZipsFunction.Arn' DestBucket: !If [CreateZipsBucket, Ref: LambdaZipsBucket, Ref: OutputBucketName] SourceBucket: !If [ UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName, ] Prefix: !Ref QSS3KeyPrefix Objects: - functions/packages/c9bootstrap/lambda.zip - functions/packages/c9InstanceProfile/lambda.zip - functions/packages/c9DiskResize/lambda.zip C9SetupRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Path: / Policies: - PolicyName: lambda-AttachRoleC9 PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - cloudformation:DescribeStackResources - ec2:AssociateIamInstanceProfile - ec2:AuthorizeSecurityGroupIngress - ec2:DescribeInstances - ec2:DescribeInstanceStatus - ec2:DescribeInstanceAttribute - ec2:DescribeIamInstanceProfileAssociations - ec2:DescribeVolumes - ec2:DesctibeVolumeAttribute - ec2:DescribeVolumesModifications - ec2:DescribeVolumeStatus - ssm:DescribeInstanceInformation - ec2:ModifyVolume - ec2:ReplaceIamInstanceProfileAssociation - ec2:ReportInstanceStatus - ssm:SendCommand - ssm:GetCommandInvocation - s3:GetObject Resource: '*' - Effect: Allow Action: iam:PassRole Resource: !GetAtt 'Cloud9Role.Arn' - Effect: Allow Action: ['lambda:AddPermission', 'lambda:RemovePermission'] Resource: '*' - Effect: Allow Action: [ 'events:PutRule', 'events:DeleteRule', 'events:PutTargets', 'events:RemoveTargets', ] Resource: '*' C9InstanceProfileLambda: DependsOn: CopyZips Type: AWS::Lambda::Function Properties: Description: Runs custom setup actions on Cloud9 environment Handler: lambda_function.handler Runtime: python3.6 Role: !GetAtt 'C9SetupRole.Arn' Timeout: 900 Code: S3Bucket: !If [CreateZipsBucket, Ref: LambdaZipsBucket, Ref: OutputBucketName] S3Key: !Sub '${QSS3KeyPrefix}functions/packages/c9InstanceProfile/lambda.zip' C9InstanceProfile: Type: Custom::C9InstanceProfileLambda Properties: ServiceToken: !GetAtt 'C9InstanceProfileLambda.Arn' InstanceProfile: !Ref Cloud9InstanceProfile Cloud9Environment: !Ref Cloud9Env C9DiskResizeLambda: DependsOn: CopyZips Type: AWS::Lambda::Function Properties: Description: Runs custom setup actions on Cloud9 environment Handler: lambda_function.handler Runtime: python3.6 Role: !GetAtt 'C9SetupRole.Arn' Timeout: 900 Code: S3Bucket: !If [CreateZipsBucket, Ref: LambdaZipsBucket, Ref: OutputBucketName] S3Key: !Sub '${QSS3KeyPrefix}functions/packages/c9DiskResize/lambda.zip' C9DiskResize: Type: Custom::C9DiskResizeLambda Properties: ServiceToken: !GetAtt 'C9DiskResizeLambda.Arn' InstanceId: !Ref C9InstanceProfile Region: !Sub '${AWS::Region}' EBSVolumeSize: !Ref EBSVolumeSize C9BootstrapLambda: Condition: DoCustomBootstrap DependsOn: CopyZips Type: AWS::Lambda::Function Properties: Description: Runs custom setup actions on Cloud9 environment Handler: lambda_function.handler Runtime: python3.6 Role: !GetAtt 'C9SetupRole.Arn' Timeout: 900 Code: S3Bucket: !If [CreateZipsBucket, Ref: LambdaZipsBucket, Ref: OutputBucketName] S3Key: !Sub '${QSS3KeyPrefix}functions/packages/c9bootstrap/lambda.zip' C9Bootstrap: Condition: DoCustomBootstrap DependsOn: C9DiskResize Type: Custom::C9BootstrapLambda Properties: ServiceToken: !GetAtt 'C9BootstrapLambda.Arn' InstanceId: !Ref C9InstanceProfile BootstrapPath: !Ref BootstrapScriptS3Uri BootstrapArguments: !Ref BootstrapArguments Outputs: Cloud9Env: Description: Cloud9 Instance Name Value: !Ref Cloud9Env