def wrapper(*args, **kwargs): kwargs['services'] = { 'sysvinit': InitServices( { 'cfn-hup': InitService( ensureRunning='true', enabled='true', files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ] ) } ) } return(func(*args, **kwargs))
'AWS::StackName'), ' --resource ContainerInstances ', ' --region ', Ref('AWS::Region'), '\n', # NOQA 'runas=root\n' ]), mode='000400', owner='root', group='root') }, ), services=InitServices({ 'cfn-hup': InitService( ensureRunning='true', enabled='true', files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }), commands={ '01_add_instance_to_cluster': { 'command': Join( '', [ '#!/bin/bash\n', # NOQA 'echo ECS_CLUSTER=', # NOQA Ref('ECSCluster'), # NOQA ' >> /etc/ecs/ecs.config' ])
def add_ec2_instance(self): instance_metadata = Metadata( Init({ 'config': InitConfig( packages={'yum': { 'openvpn': [] }}, files=InitFiles({ '/etc/openvpn/server.conf': InitFile(content=Join('\n', [ 'port 1194', 'proto tcp-server', 'dev tun1', 'ifconfig 172.16.1.2 172.16.1.3', 'status server-tcp.log', 'verb 3', 'secret /etc/openvpn/static.key', 'keepalive 10 60', 'ping-timer-rem', 'persist-tun', 'persist-key', 'user nobody', 'group nobody', 'daemon', ]), mode='000644', owner='root', group='root'), '/etc/openvpn/client.ovpn': InitFile(content=Join('\n', [ 'proto tcp-client', 'remote {{public_ip}}', 'port 1194', 'dev tun', 'secret /tmp/secret.key', 'ifconfig 10.4.0.2 10.4.0.1', ]), mode='000644', owner='root', group='root'), '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', ]), mode='000400', owner='root', group='root'), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile(content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.OpenVpn.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v --stack ', Ref('AWS::StackName'), '--resource OpenVpn ', ' --region ', Ref('AWS::Region'), '\n', 'runas=root\n', ])) }), services={ 'sysvinit': InitServices({ 'openvpn': InitService(enabled=True, ensureRunning=True, files=['/etc/openvpn/server.conf']), 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }) }) })) self.ec2_instance = self.template.add_resource( ec2.Instance( "OpenVpn", ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"), InstanceType="t2.micro", KeyName=self.sceptre_user_data["keyname"], SecurityGroupIds=[Ref(self.securityGroup)], IamInstanceProfile=Ref(self.cfninstanceprofile), SubnetId=ImportValue('deploy-dev-vpc-PublicSubnet'), Metadata=instance_metadata, UserData=Base64( Join('', [ '#!/bin/bash -xe\n', 'yum install easy-rsa -y --enablerepo=epel\n', 'yum update -y aws-cfn-bootstrap\n', '/opt/aws/bin/cfn-init -v --stack ', Ref('AWS::StackName'), ' --resource OpenVpn --region ', Ref('AWS::Region'), '\n', '/opt/aws/bin/cfn-signal -e $? --stack ', Ref('AWS::StackName'), ' --resource OpenVpn --region ', Ref('AWS::Region'), '\n', 'cd /etc/openvpn\n', 'openvpn --genkey --secret static.key\n', 'aws s3 cp static.key s3://', ImportValue('deploy-dev-s3bucket-s3bucketname'), '/\n', 'sudo modprobe iptable_nat', '\n', 'echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward', '\n', 'sudo iptables -t nat -A POSTROUTING -s 10.4.0.1/2 -o eth0 -j MASQUERADE', '\n', 'external_ip=`curl http://169.254.169.254/latest/meta-data/public-ipv4`', '\n', 'sed -i "s|{{public_ip}}|$external_ip|g" /etc/openvpn/client.ovpn', '\n', 'aws s3 cp client.ovpn s3://', ImportValue('deploy-dev-s3bucket-s3bucketname'), '\n', ])), CreationPolicy=CreationPolicy(ResourceSignal=ResourceSignal( Timeout='PT15M')), Tags=Tags(Name="vpn-server"), ))
'action=/opt/aws/bin/cfn-init -v ', ' --stack ', ref_stack_name, ' --resource WebServerInstance ', ' --region ', ref_region, '\n', 'runas=root\n', ]))}), services={ 'sysvinit': InitServices({ 'httpd': InitService( enabled=True, ensureRunning=True), 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ])})})})) instance = t.add_resource( Instance( 'WebServerInstance', Metadata=instance_metadata, ImageId=FindInMap( 'AWSRegionArch2AMI', Ref('AWS::Region'), FindInMap( 'AWSInstanceType2Arch',
def build_template(keyPair, instanceType): ''' Builds the CloudFormation template which will create EC2 and supporting resources. ''' print print '################ 2. Template Build Phase ################' print 'Starting CloudFormation template build.' ### Template Info ### mini_template = Template() # Define template version and description mini_template.add_version('2010-09-09') mini_template.add_description( 'Provisions VPC, IGW, Route Table, Subnet, and EC2 instance in AWS to support a static website.' ) ### Parameters ### instance_type = mini_template.add_parameter( Parameter( 'InstanceType', Type='String', Description='EC2 instance type', Default=instanceType, AllowedValues=[ 't1.micro', 't2.micro', 't2.small', 't2.medium', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'm3.medium', 'm3.large', 'm3.xlarge', 'm3.2xlarge', 'm4.large', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'c1.medium', 'c1.xlarge', 'c3.large', 'c3.xlarge', 'c3.2xlarge', 'c3.4xlarge', 'c3.8xlarge', 'c4.large', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', 'g2.2xlarge', 'r3.large', 'r3.xlarge', 'r3.2xlarge', 'r3.4xlarge', 'r3.8xlarge', 'i2.xlarge', 'i2.2xlarge', 'i2.4xlarge', 'i2.8xlarge', 'd2.xlarge', 'd2.2xlarge', 'd2.4xlarge', 'd2.8xlarge', 'hi1.4xlarge', 'hs1.8xlarge', 'cr1.8xlarge', 'cc2.8xlarge', 'cg1.4xlarge' ], ConstraintDescription='must be a valid EC2 instance type.', )) ### Mappings ### # AMI Mapping for Amazon Linux AMI as of 03-Jan-2017 mini_template.add_mapping( 'AWSRegionArch2AMI', { 'us-east-1': { 'HVM64': 'ami-9be6f38c' }, 'us-east-2': { 'HVM64': 'ami-38cd975d' }, 'us-west-1': { 'HVM64': 'ami-b73d6cd7' }, 'us-west-2': { 'HVM64': 'ami-1e299d7e' }, 'ca-central-1': { 'HVM64': 'ami-eb20928f' }, 'eu-west-1': { 'HVM64': 'ami-c51e3eb6' }, 'eu-west-2': { 'HVM64': 'ami-bfe0eadb' }, 'eu-central-1': { 'HVM64': 'ami-211ada4e' }, 'ap-southeast-1': { 'HVM64': 'ami-4dd6782e' }, 'ap-southeast-2': { 'HVM64': 'ami-28cff44b' }, 'ap-northeast-1': { 'HVM64': 'ami-9f0c67f8' }, 'ap-northeast-2': { 'HVM64': 'ami-94bb6dfa' }, 'ap-south-1': { 'HVM64': 'ami-9fc7b0f0' }, 'sa-east-1': { 'HVM64': 'ami-bb40d8d7' } }) ### Resources ### # VPC vpc = mini_template.add_resource( VPC('VPC', CidrBlock='172.16.0.0/16', EnableDnsSupport='True', EnableDnsHostnames='True', Tags=Tags(Name=stack_name + '-vpc', Project=stack_name))) # Internet Gateway igw = mini_template.add_resource( InternetGateway('InternetGateway', Tags=Tags(Name=stack_name + '-igw', Project=stack_name))) # Attach IGW to VPC attach_gateway = mini_template.add_resource( VPCGatewayAttachment('AttachGateway', VpcId=Ref(vpc), InternetGatewayId=Ref(igw))) # Route Table route_table = mini_template.add_resource( RouteTable('RouteTable', VpcId=Ref(vpc), Tags=Tags(Name=stack_name + '-routetable', Project=stack_name))) # Route 0.0.0.0 -> IGW route01 = mini_template.add_resource( Route('Route', DependsOn='AttachGateway', GatewayId=Ref(igw), DestinationCidrBlock='0.0.0.0/0', RouteTableId=Ref(route_table))) # Subnet subnet = mini_template.add_resource( Subnet('Subnet', CidrBlock='172.16.10.0/24', VpcId=Ref(vpc), MapPublicIpOnLaunch='True', Tags=Tags(Name=stack_name + '-subnet', Project=stack_name))) # Subnet -> Route Table subnet_route_associate = mini_template.add_resource( SubnetRouteTableAssociation('SubnetRouteTableAssociation', SubnetId=Ref(subnet), RouteTableId=Ref(route_table))) # Security Group allowing access via SSH and HTTP web_security_group = mini_template.add_resource( SecurityGroup('WebSecurityGroup', GroupDescription= 'Enable access to the web server on ports 80 and 22.', VpcId=Ref(vpc), Tags=Tags(Name=stack_name + '-securitygroup', Project=stack_name), SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0') ])) # Metadata to install Apache ec2_metadata = Metadata( Init({ 'config': InitConfig( packages={'yum': { 'httpd': [] }}, files=InitFiles({ '/var/www/html/index.html': InitFile( content= '<html><body><h2>Automation for the People!</h2></body></html>', mode='000644', owner='root', group='root') }), services={ 'sysvinit': InitServices({ 'httpd': InitService(enabled=True, ensureRunning=True) }) }) })) # EC2 Instance ec2 = mini_template.add_resource( Instance('Ec2Instance', ImageId=FindInMap('AWSRegionArch2AMI', Ref('AWS::Region'), 'HVM64'), Metadata=ec2_metadata, InstanceType=Ref(instance_type), KeyName=keyPair, SecurityGroupIds=[ Ref(web_security_group), ], SubnetId=Ref(subnet), Tags=Tags(Name=stack_name + '-ec2', Project=stack_name), CreationPolicy=CreationPolicy(ResourceSignal=ResourceSignal( Timeout='PT15M')), UserData=Base64( Join('', [ '#!/bin/bash -x\n', 'yum update -y\n', 'yum update -y aws-cfn-bootstrap\n', '/opt/aws/bin/cfn-init -v ', ' --stack ', Ref('AWS::StackName'), ' --resource Ec2Instance ', ' --region ', Ref('AWS::Region'), '\n', '/opt/aws/bin/cfn-signal -e $? ', ' --stack ', Ref('AWS::StackName'), ' --resource Ec2Instance ', ' --region ', Ref('AWS::Region'), '\n', ])))) ### Outputs ### # Output the Public DNS address for the EC2 instance mini_template.add_output( Output('URL', Description='HTTP Server URL', Value=Join('', ['http://', GetAtt('Ec2Instance', 'PublicDnsName')]))) print 'CloudFormation template build is completed.' return mini_template
ref_region, "\n", "runas=root\n", ], ) ), } ), services={ "sysvinit": InitServices( { "httpd": InitService(enabled=True, ensureRunning=True), "cfn-hup": InitService( enabled=True, ensureRunning=True, files=[ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf", ], ), } ) }, ) } ) ) instance = t.add_resource( Instance( "WebServerInstance",
"\n", # NOQA "runas=root\n", ], ), mode="000400", owner="root", group="root", ), }, ), services=InitServices( { "cfn-hup": InitService( ensureRunning="true", enabled="true", files=[ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf", ], ) } ), commands={ "01_add_instance_to_cluster": { "command": Join( "", [ "#!/bin/bash\n", # NOQA "echo ECS_CLUSTER=", # NOQA Ref("ECSCluster"), # NOQA " >> /etc/ecs/ecs.config", ],
def main(): """Generates the CloudFormation template""" template = Template() template.add_version('2010-09-09') template.add_description( 'This template deploys an ECS cluster to the ' + 'provided VPC and subnets using an Auto Scaling Group') # Parameters # EnvironmentName env_name_param = template.add_parameter( Parameter( 'EnvironmentName', Type='String', Description= 'An environment name that will be prefixed to resource names', )) # InstanceType instance_type_param = template.add_parameter( Parameter( 'InstanceType', Type='String', Default='t2.nano', Description= 'Which instance type should we use to build the ECS cluster?', AllowedValues=[ 't2.nano', 't2.micro', 't2.small', 't2.medium', 't2.large', 't2.xlarge', 't2.2xlarge', ], )) # ClusterSize cluster_size_param = template.add_parameter( Parameter( 'ClusterSize', Type='Number', Description='How many ECS hosts do you want to initially deploy?', Default='1', )) # VPC template.add_parameter( Parameter( 'VPC', Type='AWS::EC2::VPC::Id', Description= 'Choose which VPC this ECS cluster should be deployed to', )) # Subnets subnets_param = template.add_parameter( Parameter( 'Subnets', Type='List<AWS::EC2::Subnet::Id>', Description= 'Choose which subnets this ECS cluster should be deployed to', )) # SecurityGroup sg_param = template.add_parameter( Parameter( 'SecurityGroup', Type='AWS::EC2::SecurityGroup::Id', Description= 'Select the Security Group to use for the ECS cluster hosts', )) # Mappings # AWSRegionToAMI template.add_mapping( 'AWSRegionToAMI', { 'us-east-1': { 'AMI': 'ami-a58760b3' }, 'us-east-2': { 'AMI': 'ami-a6e4bec3' }, 'us-west-1': { 'AMI': 'ami-74cb9b14' }, 'us-west-2': { 'AMI': 'ami-5b6dde3b' }, 'eu-west-1': { 'AMI': 'ami-e3fbd290' }, 'eu-west-2': { 'AMI': 'ami-77f6fc13' }, 'eu-central-1': { 'AMI': 'ami-38dc1157' }, 'ap-northeast-1': { 'AMI': 'ami-30bdce57' }, 'ap-southeast-1': { 'AMI': 'ami-9f75ddfc' }, 'ap-southeast-2': { 'AMI': 'ami-cf393cac' }, 'ca-central-1': { 'AMI': 'ami-1b01b37f' }, }, ) # Resources ecs_role = template.add_resource( Role( 'ECSRole', Path='/', RoleName=Sub('${EnvironmentName}-ECSRole-${AWS::Region}'), AssumeRolePolicyDocument=awacs.aws.Policy(Statement=[ awacs.aws.Statement( Effect=awacs.aws.Allow, Action=[awacs.aws.Action('sts', 'AssumeRole')], Principal=awacs.aws.Principal('Service', ['ec2.amazonaws.com']), ), ]), Policies=[ Policy( PolicyName='ecs-service', PolicyDocument=awacs.aws.Policy(Statement=[ awacs.aws.Statement( Effect=awacs.aws.Allow, Action=[ awacs.aws.Action('ecs', 'CreateCluster'), awacs.aws.Action( 'ecs', 'DeregisterContainerInstance'), awacs.aws.Action('ecs', 'DiscoverPollEndpoint'), awacs.aws.Action('ecs', 'Poll'), awacs.aws.Action('ecs', 'RegisterContainerInstance'), awacs.aws.Action('ecs', 'StartTelemetrySession'), awacs.aws.Action('ecs', 'Submit*'), awacs.aws.Action('logs', 'CreateLogStream'), awacs.aws.Action( 'ecr', 'BatchCheckLayerAvailability'), awacs.aws.Action('ecr', 'BatchGetImage'), awacs.aws.Action('ecr', 'GetDownloadUrlForLayer'), awacs.aws.Action('ecr', 'GetAuthorizationToken'), ], Resource=['*'], ), ], ), ), ], )) ecs_instance_profile = template.add_resource( InstanceProfile( 'ECSInstanceProfile', Path='/', Roles=[Ref(ecs_role)], )) # ECSCluster ecs_cluster = template.add_resource( Cluster( 'ECSCluster', ClusterName=Ref(env_name_param), )) instance_metadata = Metadata( Init({ 'config': InitConfig( commands={ '01_add_instance_to_cluster': { 'command': Join('', [ '#!/bin/bash\n', 'echo ECS_CLUSTER=', Ref(ecs_cluster), ' >> /etc/ecs/ecs.config' ]) }, }, files=InitFiles({ '/etc/cfn/cfn-hup.conf': InitFile( mode='000400', owner='root', group='root', content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n' ]), ), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( mode='000400', owner='root', group='root', content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.ContainerInstances.Metadata.AWS::CloudFormation::Init\n' 'action=/opt/aws/bin/cfn-init -v --region ', Ref('AWS::Region'), ' --stack ', Ref('AWS::StackId'), ' --resource ECSLaunchConfiguration\n' ]), ) }), services=InitServices({ 'cfn-hup': InitService(enabled='true', ensureRunning='true', files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }), ) })) ecs_launch_config = template.add_resource( LaunchConfiguration( 'ECSLaunchConfiguration', ImageId=FindInMap('AWSRegionToAMI', Ref('AWS::Region'), 'AMI'), InstanceType=Ref(instance_type_param), SecurityGroups=[Ref(sg_param)], IamInstanceProfile=Ref(ecs_instance_profile), UserData=Base64( Join('', [ '#!/bin/bash\n', 'yum install -y aws-cfn-bootstrap\n', '/opt/aws/bin/cfn-init -v --region ', Ref('AWS::Region'), ' --stack ', Ref('AWS::StackName'), ' --resource ECSLaunchConfiguration\n', '/opt/aws/bin/cfn-signal -e $? --region ', Ref('AWS::Region'), ' --stack ', Ref('AWS::StackName'), ' --resource ECSAutoScalingGroup\n', ])), Metadata=instance_metadata, )) # ECSAutoScalingGroup: template.add_resource( AutoScalingGroup( 'ECSAutoScalingGroup', VPCZoneIdentifier=Ref(subnets_param), LaunchConfigurationName=Ref(ecs_launch_config), MinSize=Ref(cluster_size_param), MaxSize=Ref(cluster_size_param), DesiredCapacity=Ref(cluster_size_param), Tags=ASTags(Name=(Sub('${EnvironmentName} ECS host'), True)), CreationPolicy=CreationPolicy( ResourceSignal=ResourceSignal(Timeout='PT15M'), ), UpdatePolicy=UpdatePolicy( AutoScalingRollingUpdate=AutoScalingRollingUpdate( MinInstancesInService='1', MaxBatchSize='1', PauseTime='PT15M', WaitOnResourceSignals=True, )), )) # Output template.add_output( Output( 'Cluster', Description='A reference to the ECS cluster', Value=Ref(ecs_cluster), )) print(template.to_json())