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
def main(): '''Function: Generates the Cloudformation template''' template = Template() template.add_description("A target server for CI/CD tests.") keyname_param = template.add_parameter( Parameter( 'KeyName', Description='An existing EC2 KeyPair.', ConstraintDescription='An existing EC2 KeyPair.', Type='AWS::EC2::KeyPair::KeyName', )) template.add_mapping( 'RegionMap', { 'ap-south-1': { 'ami': 'ami-0dba8796fe499ae48' }, 'eu-west-3': { 'ami': 'ami-07b2287c6776361c8' }, 'eu-north-1': { 'ami': 'ami-34c14f4a' }, 'eu-west-2': { 'ami': 'ami-0573b1dbbd809d6c3' }, 'eu-west-1': { 'ami': 'ami-001b0e20a92d8db1e' }, 'ap-northeast-2': { 'ami': 'ami-0dc961dd0c2c83bdd' }, 'ap-northeast-1': { 'ami': 'ami-0f2c38ac2e37197be' }, 'sa-east-1': { 'ami': 'ami-04ab6be036f8635bd' }, 'ca-central-1': { 'ami': 'ami-0de195e1958cc0d52' }, 'ap-southeast-1': { 'ami': 'ami-08540b8d2f7fa85a5' }, 'ap-southeast-2': { 'ami': 'ami-0bbcf853aaf6ca4a6' }, 'eu-central-1': { 'ami': 'ami-0332a5c40cf835528' }, 'us-east-1': { 'ami': 'ami-0edd3706ab2e952c4' }, 'us-east-2': { 'ami': 'ami-050553a7784d00d21' }, 'us-west-1': { 'ami': 'ami-065ebd3e6b63c75d5' }, 'us-west-2': { 'ami': 'ami-00f13b45242aff065' } }) ec2_security_group = template.add_resource( ec2.SecurityGroup( 'EC2SecurityGroup', Tags=[ { 'Key': 'Name', 'Value': Ref('AWS::StackName') }, ], GroupDescription='EC2 Security Group', SecurityGroupIngress=[ ec2.SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='0.0.0.0/0', Description='SSH'), ec2.SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0', Description='HTTP'), ec2.SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0', Description='HTTPS'), ], )) ec2_instance = template.add_resource( ec2.Instance( 'Instance', Metadata=Metadata( Init({ "config": InitConfig(files=InitFiles({ "/tmp/instance.txt": InitFile(content=Ref('AWS::StackName'), mode="000644", owner="root", group="root") }), ) }), ), CreationPolicy=CreationPolicy(ResourceSignal=ResourceSignal( Timeout='PT15M')), Tags=[ { 'Key': 'Name', 'Value': Ref('AWS::StackName') }, ], ImageId=FindInMap('RegionMap', Ref('AWS::Region'), 'ami'), InstanceType='t2.micro', KeyName=Ref(keyname_param), SecurityGroups=[Ref(ec2_security_group)], UserData=Base64( Join('', [ '#!/bin/bash -x\n', 'exec > /tmp/user-data.log 2>&1\n', 'unset UCF_FORCE_CONFFOLD\n', 'export UCF_FORCE_CONFFNEW=YES\n', 'ucf --purge /boot/grub/menu.lst\n', 'export DEBIAN_FRONTEND=noninteractive\n', 'apt-get update\n', 'apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy upgrade\n', 'apt-get install -y nginx supervisor build-essential libssl-dev libffi-dev python-pip python3-pip python3-dev python3-setuptools python3-venv\n', 'pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n', '# Signal Cloudformation when set up is complete\n', '/usr/local/bin/cfn-signal -e $? --resource=Instance --region=', Ref('AWS::Region'), ' --stack=', Ref('AWS::StackName'), '\n', ])))) template.add_output([ Output( 'InstanceDnsName', Description='PublicDnsName', Value=GetAtt(ec2_instance, 'PublicDnsName'), ), ]) print(template.to_yaml())
"config": InitConfig( packages={"yum": {"httpd": []}}, files=InitFiles( { "/var/www/html/index.html": InitFile( content=Join( "\n", [ '<img \ src="https://s3.amazonaws.com/cloudformation-examples/\ cloudformation_graphic.png" alt="AWS CloudFormation Logo"/>', "<h1>\ Congratulations, you have successfully launched the AWS CloudFormation sample.\ </h1>", ], ), mode="000644", owner="root", group="root", ), "/etc/cfn/cfn-hup.conf": InitFile( content=Join( "", [ "[main]\n", "stack=", ref_stack_id, "\n", "region=", ref_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.WebServerInstance.\ Metadata.AWS::CloudFormation::Init\n", "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", ], ), } ) }, )
"config": InitConfig( files=InitFiles( { "/etc/cfn/cfn-hup.conf": InitFile( content=Join( "", [ "[main]\n", "stack=", Ref("AWS::StackId"), # NOQA "\n", "region=", Ref("AWS::Region"), "\n", ], ), # NOQA 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.ContainerInstances.Metadata.AWS::CloudFormation::Init\n", # NOQA "action=/opt/aws/bin/cfn-init -v ", "--stack ", Ref("AWS::StackName"), # NOQA " --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", ], ) }, # NOQA "02_install_ssm_agent": { "command": Join( "", [ "#!/bin/bash\n", "yum -y update\n", # NOQA "curl https://amazon-ssm-eu-west-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm\n", # NOQA "yum install -y amazon-ssm-agent.rpm", # NOQA ], ) }, }, )
def main(): '''Function: Generates the Cloudformation template''' template = Template() keyname_param = template.add_parameter( Parameter( 'KeyName', Description='Name of an existing EC2 KeyPair for SSH access', ConstraintDescription='must be the name of an existing EC2 KeyPair.', Type='AWS::EC2::KeyPair::KeyName', ) ) password_param = template.add_parameter( Parameter( 'PassWord', Type='String', NoEcho=True, MinLength=8, MaxLength=64, Description='Password for the admin account', ConstraintDescription='A complex password at least eight chars long with alphanumeric characters, dashes and underscores.', AllowedPattern="[-_a-zA-Z0-9]*", ) ) ec2_security_group = template.add_resource( ec2.SecurityGroup( 'SecurityGroup', GroupDescription='SSH, HTTP/HTTPS open for 0.0.0.0/0', SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='0.0.0.0/0'), ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0'), ], ) ) ec2_instance = template.add_resource( ec2.Instance( 'Instance', Metadata=Metadata( Init({ "config": InitConfig( files=InitFiles({ "/etc/nginx/conf.d/app.conf": InitFile( content='server { listen 80 default_server; listen [::]:80 default_server; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }', mode="000644", owner="root", group="root" ) }), ) }), ), CreationPolicy=CreationPolicy( ResourceSignal=ResourceSignal( Timeout='PT15M')), Tags=[{'Key':'Name', 'Value':'Simple Stack Instance {}'.format(time.strftime('%c'))},], ImageId='ami-39c28c41', InstanceType='t2.micro', KeyName=Ref(keyname_param), SecurityGroups=[Ref(ec2_security_group)], UserData=Base64( Join( '', [ '#!/bin/bash -x\n', 'exec > /tmp/user-data.log 2>&1\n' 'apt-get update\n', 'apt-get install -y python-pip\n', 'pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n', 'apt-get install -y nginx\n', 'apt-get install -y openjdk-8-jdk\n', '/usr/local/bin/cfn-init --verbose --resource=Instance --region=', Ref('AWS::Region'), ' --stack=', Ref('AWS::StackName'), '\n', 'unlink /etc/nginx/sites-enabled/default\n' 'systemctl reload nginx\n', '/usr/local/bin/cfn-signal -e 0 --resource Instance --region us-west-2 --stack simple\n', ] ) ) ) ) template.add_output([ Output( 'PublicDnsName', Description='PublicDnsName', Value=GetAtt(ec2_instance, 'PublicDnsName'), ), ]) print(template.to_yaml())
InitConfig( commands={'update_yum_packages': { 'command': 'yum update -y' }}, files=InitFiles({ # setup .bashrc ec2-user '/home/ec2-user/.bashrc': InitFile(content=Join( '', ['export PATH="/home/ec2-user/miniconda/bin:$PATH"\n']), owner='ec2-user', mode='000400', group='ec2-user'), # setup .bashrc root '/root/.bashrc': InitFile(content=Join('', [ 'export PATH="/home/ec2-user/miniconda/bin:$PATH"\n' f'export STREAM_NAME="{STREAM_NAME}"\n', f'export PRODUCER_NAME="{SERVER_NAME}"\n', f'export TWITTER_KEYWORDS="{TWITTER_KEYWORDS}"\n', 'export ENV="production"\n' ]), owner='root', mode='000400', group='root'), # configure cfn-hup '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', 'interval=2', '\n', ]), mode='000400', owner='root', group='root'), # setup cfn-auto-reloader '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile(content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', f'path=Resources.{SERVER_NAME}.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v', ' --stack ', Ref('AWS::StackId'), f' --resource {SERVER_NAME}', ' --region ', Ref('AWS::Region'), '\n' 'runas=root\n', ])) }), services={ 'sysvinit': InitServices({ 'cfn-hup': InitService(enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }) })
InitConfig( files=InitFiles( { '/etc/cfn/cfn-hup.conf': InitFile( content=Join( '', [ '[main]\n', 'stack=', Ref('AWS::StackId'), # NOQA '\n', 'region=', Ref('AWS::Region'), '\n' ]), # NOQA 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.ContainerInstances.Metadata.AWS::CloudFormation::Init\n', # NOQA 'action=/opt/aws/bin/cfn-init -v ', '--stack ', Ref( # NOQA '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' ]) }, # NOQA '02_install_ssm_agent': { 'command': Join( '', [ '#!/bin/bash\n', 'yum -y update\n', # NOQA 'curl https://amazon-ssm-eu-west-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm\n', # NOQA 'yum install -y amazon-ssm-agent.rpm' # NOQA ]) } })
def main(): '''Function: Generates the Cloudformation template''' template = Template() template.set_description("Server Stack") keyname_param = template.add_parameter( Parameter( 'KeyName', Description='An existing EC2 KeyPair.', ConstraintDescription='An existing EC2 KeyPair.', Type='AWS::EC2::KeyPair::KeyName', ) ) template.add_mapping('RegionMap', {'eu-north-1': {'ami': 'ami-a536bedb'}, 'ap-south-1': {'ami': 'ami-00b2a5e29f669c903'}, 'eu-west-3': {'ami': 'ami-0d8581d2794d7df68'}, 'eu-west-2': {'ami': 'ami-02369579484abae2e'}, 'eu-west-1': {'ami': 'ami-0c17a2bccea3e36f9'}, 'ap-northeast-2': {'ami': 'ami-05daa9d0230f30d79'}, 'ap-northeast-1': {'ami': 'ami-03a90fe15b63befea'}, 'sa-east-1': {'ami': 'ami-0c04bf4cfbf3e9dbe'}, 'ca-central-1': {'ami': 'ami-013d2a414e834a144'}, 'ap-southeast-1': {'ami': 'ami-07ed1f021e2eea7cb'}, 'ap-southeast-2': {'ami': 'ami-068e6346d66ed62c8'}, 'eu-central-1': {'ami': 'ami-00aa61be0e9a8f948'}, 'us-east-1': {'ami': 'ami-0dd925351e231e8c7'}, 'us-east-2': {'ami': 'ami-06cb7cbcc0e8e90e8'}, 'us-west-1': {'ami': 'ami-0d8e4e7b60cd5f225'}, 'us-west-2': {'ami': 'ami-06ad92f74f2c20787'}}) ec2_security_group = template.add_resource( ec2.SecurityGroup( 'EC2SecurityGroup', Tags=[{'Key':'Name', 'Value':Ref('AWS::StackName')},], GroupDescription='EC2 Security Group', SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='0.0.0.0/0', Description='SSH'), ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0', Description='HTTP'), ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0', Description='HTTPS'), ], ) ) ec2_instance = template.add_resource( ec2.Instance( 'Instance', Metadata=Metadata( Init({ "config": InitConfig( files=InitFiles({ "/tmp/instance.txt": InitFile( content=Ref('AWS::StackName'), mode="000644", owner="root", group="root" ) }), ) }), ), CreationPolicy=CreationPolicy( ResourceSignal=ResourceSignal(Timeout='PT15M') ), Tags=[{'Key':'Name', 'Value':Ref('AWS::StackName')},], ImageId=FindInMap('RegionMap', Ref('AWS::Region'), 'ami'), InstanceType='t2.2xlarge', KeyName=Ref(keyname_param), SecurityGroups=[Ref(ec2_security_group)], UserData=Base64( Join( '', [ '#!/bin/bash -x\n', 'exec > /tmp/user-data.log 2>&1\n', 'unset UCF_FORCE_CONFFOLD\n', 'export UCF_FORCE_CONFFNEW=YES\n', 'ucf --purge /boot/grub/menu.lst\n', 'export DEBIAN_FRONTEND=noninteractive\n', 'apt-get update\n', 'apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy upgrade\n', 'apt-get install -y python-pip\n', 'pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n', '# Signal Cloudformation when set up is complete\n', '/usr/local/bin/cfn-signal -e $? --resource=Instance --region=', Ref('AWS::Region'), ' --stack=', Ref('AWS::StackName'), '\n', ] ) ) ) ) template.add_resource( ec2.EIP( 'ElasticIP', InstanceId=Ref(ec2_instance), Domain='vpc' ) ) template.add_output([ Output( 'InstanceDnsName', Description='PublicDnsName', Value=GetAtt(ec2_instance, 'PublicDnsName'), ), ]) print(template.to_yaml())
InitConfig( commands={ 'update_yum_packages': { 'command': 'yum update -y' }, 'download_miniconda': { 'command': 'su - ec2-user -c "wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /home/ec2-user/miniconda.sh"', }, 'install_miniconda': { 'command': 'su - ec2-user -c "bash /home/ec2-user/miniconda.sh -b -p /home/ec2-user/miniconda"', }, 'remove_installer': { 'command': 'rm -rf /home/ec2-user/miniconda.sh', } }, files=InitFiles({ # setup .bashrc '/home/ec2-user/.ssh/authorized_keys': InitFile(content=Join('', [ 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCjKxODWLSrmQAemYnpvYchmy7bwWvIKNWpHtfRiD7UKqnUV0euoFWIr9j+OwiNyMp/iopZQh7A8c+B4TYI8pd///J7ZWPSipndJkWc4HrnU37X66mKInGYIaPZAfek69eeUkl5cekqkEd6l6WsBUlrjPvMYtyGdDtd42M+aNQoy1TWq2C/6x0gBQaY/CUvHFBrMHr5ObhZvN7ou6PSyBCGgQxFf5jmnwSzeBRc/iWxMBltM/SQSTAgyKWdolcgBNTOTre5z8R8FCv/CIsfLoqUFuWthrT3YfpG1iOWlL3GBm8XxXlgrmvMUhV1qvcO/1no6ZeSp8VQMiTYkvAOQ7Hd\n' ]), owner='ec2-user', mode='000400', group='ec2-user'), # setup .bashrc '/home/ec2-user/.bashrc': InitFile(content=Join( '', ['export PATH="/home/ec2-user/miniconda/bin:$PATH"\n']), owner='ec2-user', mode='000400', group='ec2-user'), # configure cfn-hup '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', 'interval=2', '\n', ]), mode='000400', owner='root', group='root'), # setup cfn-auto-reloader '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile(content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.Bastion.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v', ' --stack ', Ref('AWS::StackId'), ' --resource Bastion', ' --region ', Ref('AWS::Region'), '\n' 'runas=root\n', ])) }), services={ 'sysvinit': InitServices({ 'cfn-hup': InitService(enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }) })
IamInstanceProfile=Ref(netkan_profile), KeyName='techman83_alucard', SecurityGroups=['ckan-bot'], UserData=Base64(netkan_userdata), # t3 instances are unlimited by default CreditSpecification=CreditSpecification(CPUCredits='standard'), Tags=[ Tag(Key='Name', Value='NetKAN Indexer'), Tag(Key='Service', Value='Indexer'), ], Metadata=Metadata( Init({ 'config': InitConfig( files=InitFiles({ '/etc/cfn/cfn-hup.conf': cfn_hup, '/etc/cfn/hooks.d/cfn-auto-reloader.conf': reloader, '/etc/docker/daemon.json': docker, })), 'services': { 'sysvinit': { 'cfn': cfn_service, 'docker': docker_service, } }, })), BlockDeviceMappings=[ BlockDeviceMapping(DeviceName='/dev/xvdh', Ebs=EBSBlockDevice( VolumeSize='50', VolumeType='standard', ))
template.add_resource(target_group) template.add_resource(listener) # Setup the ASG & launch config launch_config = LaunchConfiguration( "LaunchConfig", ImageId=image_id, IamInstanceProfile=Ref(example_instance_profile), InstanceType=instance_type, Metadata=Metadata( Init({ 'config': InitConfig( commands={ "01_run_container": { "command": "docker run -d -p 80:8000 --name whoami -t jwilder/whoami" } }) })), SecurityGroups=[Ref(ec2_security_group)]) auto_scale_group = AutoScalingGroup( "AutoscaleGroup", MinSize=autoscaling_min, MaxSize=autoscaling_max, DesiredCapacity=autoscaling_desired, LaunchConfigurationName=Ref(launch_config), TargetGroupARNs=[GetAtt(target_group, "LoadBalancerArns")], VPCZoneIdentifier=subnet_ids) template.add_resource(launch_config) template.add_resource(auto_scale_group)
'config': InitConfig( packages={'yum': {'httpd': []}}, commands={ 'copytest': {'command': 'cp /home/ec2-user/test.txt /var/www/html/'} }, files=InitFiles({ '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', ['[main]\n', 'stack=', ref_stack_id, '\n', 'region=', ref_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.WebServerInstance.\ Metadata.AWS::CloudFormation::Init\n', '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' ])})})}))
def test_using_load_balancer(self): test_stack_name = "TestALB" init_cf_env(test_stack_name) ### t = Template() load_balancer_sg = ts_add_security_group( t, name="LoadBalancerSecurityGroup") instance_sg = ts_add_security_group(t) load_balancer = t.add_resource( LoadBalancer( "MyLoadBalancer", SecurityGroups=[Ref(load_balancer_sg)], # The ALB is publicly accessible. # (use `internal` instead of `internet-facing` to define a load balancer reachable from private network only) Scheme='internet-facing', Subnets=[get_subnet(index=0), get_subnet(index=1) ], # Attaches the ALB to the subnets Type='application')) target_group = t.add_resource( TargetGroup( "MyTargetGroup", HealthCheckIntervalSeconds=10, HealthCheckProtocol='HTTP', HealthCheckPath='/index.html', HealthCheckTimeoutSeconds=5, HealthyThresholdCount=3, UnhealthyThresholdCount=2, Matcher=Matcher( HttpCode='200-299' ), # If HTTP status code is 2XX, the backend is considered healthy. Port= 80, # The web server on the EC2 instances listens on port 80. Protocol='HTTP', VpcId=get_default_vpc(), )) listener = t.add_resource( Listener( "MyListener", LoadBalancerArn=Ref(load_balancer), Port=80, Protocol= 'HTTP', # The load balancer listens on port 80 for HTTP requests. DefaultActions=[ Action( Type='forward', # TargetGroupARN is the connection between the ALB and the auto-scaling group TargetGroupArn=Ref(target_group), ) ])) launch_config = t.add_resource( LaunchConfiguration( "MyLaunchConfiguration", ImageId=get_linux2_image_id(), InstanceType='m4.xlarge', KeyName=KEY, SecurityGroups=[Ref(instance_sg)], AssociatePublicIpAddress=True, InstanceMonitoring=False, UserData=Base64( Join('', [ '#!/bin/bash -xe\n', '/opt/aws/bin/cfn-init -v --stack ', Ref('AWS::StackName'), ' --resource MyLaunchConfiguration ', ' --region ', Ref('AWS::Region'), '\n' ])), Metadata=Metadata( Init({ 'config': InitConfig( packages={'yum': { 'httpd': [] }}, files={ '/tmp/config': { 'content': Join('\n', [ '#!/bin/bash -ex', 'PRIVATE_IP=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`', 'echo "$PRIVATE_IP" > index.html', ]), 'mode': '000500', 'owner': 'root', 'group': 'root', } }, commands={ '01_config': { 'command': "/tmp/config", 'cwd': '/var/www/html' } }, services={ 'sysvinit': { 'httpd': { 'enabled': True, 'ensureRunning': True } } }) })))) auto_scaling_group = t.add_resource( AutoScalingGroup( "MyAutoScalingGroup", LaunchConfigurationName=Ref(launch_config), DesiredCapacity=2, MinSize=2, MaxSize=2, VPCZoneIdentifier=[get_subnet(index=0), get_subnet(index=1)], TargetGroupARNs=[ Ref(target_group) ], # Registers new EC2 instances with the default target group. Tags=[ Tag( "Name", test_stack_name, True ) # 'True' means: Attaches the same tags to the virtual machine started by this auto-scaling group ])) t.add_output([ Output("URL", Value=Sub('http://${MyLoadBalancer.DNSName}')), ]) dump_template(t, True) create_stack(test_stack_name, t) outputs = get_stack_outputs(test_stack_name) lb_url = get_output_value(outputs, 'URL') private_ips = set() for i in range(10): private_ips.add(run(f'curl {lb_url}', True)) self.assertEqual(len(private_ips), 2)
def create_env(name, overrides, key_name, region, vpc_id, build, internal_domain, base_stack=None): t = Template() t.add_description("""\ microservices stack""") overrides = json.loads(overrides) if overrides else {} # creating private hosted zone (dns) hosted_zone = create_private_dns(t, internal_domain, vpc_id, region) # creating codecommit repo (if not exists) codecommit = boto3.client('codecommit', region_name=region) try: repo_res = codecommit.get_repository( repositoryName=name ) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'RepositoryDoesNotExistException': repo_res = None new_repo = repo_res is not None if not repo_res: repo_res = codecommit.create_repository( repositoryName=name ) repo = repo_res['repositoryMetadata']['cloneUrlSsh'] # creating config service role_profile = create_ec2_instance_role(t, 'configserver') instance_info = get_instance_info('configserver', build, 't2.micro', role_profile['profile'], region, base_stack, overrides) commands = { "setappenvs": { "command": "echo \"\nspring.cloud.config.server.git.uri={}\n\" >> /home/ubuntu/application.properties".format(repo) } } if new_repo: # restarting the git repo with values for app\default (required for config service health) commands["initgit"] = { "command": "git init && git remote add origin {} && git add . && git commit -m \"init\" && git push origin master".format(repo), "cwd": "/home/ubuntu/gitinit" } metadata = Metadata( Init({ "config": InitConfig( commands=commands ) }), ) config_service = create_microservice_asg_with_elb( t, instance_info['ami'], key_name, instance_info['profile'], instance_info['instanceType'], 'configserver', vpc_id, elb_port=8888, instance_port=8888, region=region, min_size=2, max_size=2, metadata=metadata ) create_private_dns_elb(t, internal_domain, 'config-service', config_service['elb']['name'], 'DnsRecordConfig') # creating eureaka service # creating avatars service ''' avatars_service = create_microservice_asg_with_elb( t, services['avatars']['ami'], key_name, services['avatars']['profile'], services['avatars']['instance_type'], 'AvatarsService', vpc_id, region=region, min_size=2, max_size=2, depends_on=config_service['asg'] ) ''' return t
def main(): '''Function: Generates the Cloudformation template''' template = Template() keyname_param = template.add_parameter( Parameter( 'KeyName', Description='Name of an existing EC2 KeyPair for SSH access', ConstraintDescription='Must be the name of an existing EC2 KeyPair.', Type='AWS::EC2::KeyPair::KeyName', ) ) password_param = template.add_parameter( Parameter( 'PassWord', Type='String', NoEcho=True, MinLength=8, MaxLength=64, Description='Password for the admin account', ConstraintDescription='A complex password at least eight chars long with alphanumeric characters, dashes and underscores.', AllowedPattern="[-_a-zA-Z0-9]*", ) ) template.add_mapping('RegionMap', {'ap-south-1': {'ami': 'ami-ee8ea481'}, 'eu-west-3': {'ami': 'ami-daf040a7'}, 'eu-west-2': {'ami': 'ami-ddb950ba'}, 'eu-west-1': {'ami': 'ami-d2414e38'}, 'ap-northeast-2': {'ami': 'ami-65d86d0b'}, 'ap-northeast-1': {'ami': 'ami-e875a197'}, 'sa-east-1': {'ami': 'ami-ccd48ea0'}, 'ca-central-1': {'ami': 'ami-c3e567a7'}, 'ap-southeast-1': {'ami': 'ami-31e7e44d'}, 'ap-southeast-2': {'ami': 'ami-23c51c41'}, 'eu-central-1': {'ami': 'ami-3c635cd7'}, 'us-east-1': {'ami': 'ami-5cc39523'}, 'us-east-2': {'ami': 'ami-67142d02'}, 'us-west-1': {'ami': 'ami-d7b355b4'}, 'us-west-2': {'ami': 'ami-39c28c41'}}) ec2_security_group = template.add_resource( ec2.SecurityGroup( 'SecurityGroup', GroupDescription='SSH, HTTP/HTTPS open for 0.0.0.0/0', SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='0.0.0.0/0'), ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0'), ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0'), ], ) ) ec2_role = template.add_resource( Role('EC2Role', AssumeRolePolicyDocument={ "Version" : "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ec2.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] }, ) ) ec2_policy = template.add_resource( ManagedPolicy( 'EC2Policy', PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Action": "ec2:*", "Resource": "*", "Effect": "Allow" } ] }, Roles=[Ref(ec2_role)] ) ) ec2_profile = template.add_resource( InstanceProfile("EC2InstanceProfile", Roles=[Ref(ec2_role)]) ) ec2_instance = template.add_resource( ec2.Instance( 'Instance', Metadata=Metadata( Init({ "config": InitConfig( files=InitFiles({ "/etc/nginx/conf.d/jenkins.conf": InitFile( content='server { listen 80 default_server; listen [::]:80 default_server; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }', mode="000644", owner="root", group="root" ) }), ) }), ), CreationPolicy=CreationPolicy( ResourceSignal=ResourceSignal(Timeout='PT15M') ), ImageId=FindInMap('RegionMap', Ref('AWS::Region'), 'ami'), InstanceType='t2.micro', IamInstanceProfile=Ref(ec2_profile), KeyName=Ref(keyname_param), SecurityGroups=[Ref(ec2_security_group)], UserData=Base64( Join( '', [ '#!/bin/bash -x\n', 'exec > /tmp/user-data.log 2>&1\n' 'unset UCF_FORCE_CONFFOLD\n', 'export UCF_FORCE_CONFFNEW=YES\n', 'ucf --purge /boot/grub/menu.lst\n', 'export DEBIAN_FRONTEND=noninteractive\n', 'echo "deb http://pkg.jenkins-ci.org/debian binary/" > /etc/apt/sources.list.d/jenkins.list\n', 'wget -q -O jenkins-ci.org.key http://pkg.jenkins-ci.org/debian-stable/jenkins-ci.org.key\n' 'apt-key add jenkins-ci.org.key\n', 'apt-get update\n', 'apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy upgrade\n', 'apt-get install -y python-pip\n', 'pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n', 'apt-get install -y nginx\n', 'apt-get install -y openjdk-8-jdk\n', 'apt-get install -y jenkins\n', '# Wait for Jenkins to Set Up\n' "until [ $(curl -o /dev/null --silent --head --write-out '%{http_code}\n' http://localhost:8080) -eq 403 ]; do sleep 1; done\n", 'sleep 10\n', '# Change the password for the admin account\n', "echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount(\"admin\", \"",Ref(password_param),"\")' | java -jar /var/cache/jenkins/war/WEB-INF/jenkins-cli.jar -s \"http://localhost:8080/\" -auth \"admin:$(cat /var/lib/jenkins/secrets/initialAdminPassword)\" groovy =\n", '/usr/local/bin/cfn-init --resource=Instance --region=', Ref('AWS::Region'), ' --stack=', Ref('AWS::StackName'), '\n', 'unlink /etc/nginx/sites-enabled/default\n', 'systemctl reload nginx\n', '/usr/local/bin/cfn-signal -e $? --resource=Instance --region=', Ref('AWS::Region'), ' --stack=', Ref('AWS::StackName'), '\n', ] ) ) ) ) template.add_output([ Output( 'PublicDnsName', Description='PublicDnsName', Value=Join('',['http://', GetAtt(ec2_instance, 'PublicDnsName'),]) ), ]) print(template.to_yaml())
Init({'config': InitConfig( commands={ 'update_yum_packages': { 'command': 'yum update -y' }, 'download_miniconda': { 'command': 'su - ec2-user -c "wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /home/ec2-user/miniconda.sh"', }, 'install_miniconda': { 'command': 'su - ec2-user -c "bash /home/ec2-user/miniconda.sh -b -p /home/ec2-user/miniconda"', }, 'remove_installer': { 'command': 'rm -rf /home/ec2-user/miniconda.sh', } }, files=InitFiles({ # setup .bashrc '/home/ec2-user/.bashrc': InitFile( content=Join('', [ 'export PATH="/home/ec2-user/miniconda/bin:$PATH"\n' ]), owner='ec2-user', mode='000400', group='ec2-user'), # configure cfn-hup '/etc/cfn/cfn-hup.conf': InitFile( content=Join('', ['[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', 'interval=2', '\n', ]), mode='000400', owner='root', group='root'), # setup cfn-auto-reloader '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( content=Join('', ['[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.DevServer.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v', ' --stack ', Ref('AWS::StackId'), ' --resource DevServer', ' --region ', Ref('AWS::Region'), '\n' 'runas=root\n', ] ) ) }), services={ 'sysvinit': InitServices({ 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) })} )
'config': InitConfig( packages={'yum': {'httpd': []}}, files=InitFiles({ '/var/www/html/index.html': InitFile(content=Join('\n', [ '<img \ src="https://s3.amazonaws.com/cloudformation-examples/\ cloudformation_graphic.png" alt="AWS CloudFormation Logo"/>', '<h1>\ Congratulations, you have successfully launched the AWS CloudFormation sample.\ </h1>']), mode='000644', owner='root', group='root'), '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', ['[main]\n', 'stack=', ref_stack_id, '\n', 'region=', ref_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.WebServerInstance.\ Metadata.AWS::CloudFormation::Init\n', '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' ])})})}))
def generate_template(): template = Template() ref_stack_id = Ref('AWS::StackId') ref_region = Ref('AWS::Region') ref_stack_name = Ref('AWS::StackName') template.add_description( 'Counter Strike Source Dedicated Server instances Stack implementing a linux ' + 'server and installing the dedicated server on it') aws_access_key = template.add_parameter( Parameter('AWSAccessKey', Type='String', Description='AWS Access Key')) aws_secret_key = template.add_parameter( Parameter('AWSSecretKey', Type='String', Description='AWS Secret Key')) css_instance_name = template.add_parameter( Parameter('CSSInstanceName', Default='css-server', Type='String', Description='The Name tag for the CSS Server instance.')) ami_id_linux = template.add_parameter( Parameter('AmiIdLinux', Default='ami-82f4dae7', Type='AWS::EC2::Image::Id', Description='Instances in the DMZ will use this AMI.')) instance_type = template.add_parameter( Parameter( 'InstanceType', Type='String', Description='Instances launched will use this EC2 Instance type.', AllowedValues=[ 't2.nano', 't2.micro', 't2.small', 't2.medium', 'c3.large', 'c3.xlarge', 'c3.2xlarge', 'c4.large', 'c4.xlarge', 'c4.2xlarge', 'm4.large' ], ConstraintDescription='must be a supported EC2 Instance type')) vpc_id = template.add_parameter(Parameter( 'VPCId', Type='String', )) public_subnet = template.add_parameter( Parameter( 'PublicSubnet1', Type='String', )) iam_role = template.add_parameter( Parameter('IAMRole', Type='String', Description='The IAM role associated with the instances.')) keyname = template.add_parameter( Parameter( 'KeyName', Type='AWS::EC2::KeyPair::KeyName', Description= 'Instances in the Auto Scaling Group will use this ssh key.')) css_init_config_script = template.add_parameter( Parameter("CSSInitConfigScript", Type="String", Description="File containing initial configuration script")) css_install_script = template.add_parameter( Parameter( "CSSInstallScript", Type="String", Description="File containing installation script for CSS server")) css_mods_tgz = template.add_parameter( Parameter("CSSModsTgz", Type="String", Description="File containing mods of the CSS server")) css_mapcycle_txt = template.add_parameter( Parameter("CSSMapcycleTxt", Type="String", Description="mapcycle.txt of the CSS server")) css_server_cfg = template.add_parameter( Parameter("CSSServerCfg", Type="String", Description="server.cfg of the CSS server")) css_rcon_password = template.add_parameter( Parameter("CSSRconPassword", Type="String", Description="RCON password of the CSS server")) bucket_name = template.add_parameter( Parameter("BucketName", Type="String", Description="Name of the S3 Bucket")) # Create Security Groups sshlocation_param = template.add_parameter( Parameter( 'SSHLocation', Description= ' The IP address range that can be used to SSH to the EC2 instances', Type='String', MinLength='9', MaxLength='18', Default='0.0.0.0/0', AllowedPattern= "(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})", ConstraintDescription=( "must be a valid IP CIDR range of the form x.x.x.x/x."), )) public_security_group = template.add_resource( SecurityGroup( 'PublicSecurityGroup', GroupDescription='Security group for instances in the DMZ', SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='icmp', FromPort='8', ToPort='-1', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp=Ref(sshlocation_param)), SecurityGroupRule(IpProtocol='tcp', FromPort='1200', ToPort='1200', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='udp', FromPort='1200', ToPort='1200', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='udp', FromPort='27005', ToPort='27005', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='27015', ToPort='27015', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='udp', FromPort='27015', ToPort='27015', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='udp', FromPort='27020', ToPort='27020', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='udp', FromPort='26901', ToPort='26901', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='icmpv6', FromPort='-1', ToPort='-1', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='1200', ToPort='1200', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='udp', FromPort='1200', ToPort='1200', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='udp', FromPort='27005', ToPort='27005', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='27015', ToPort='27015', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='udp', FromPort='27015', ToPort='27015', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='udp', FromPort='27020', ToPort='27020', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='udp', FromPort='26901', ToPort='26901', CidrIpv6='::/0') ], SecurityGroupEgress=[ SecurityGroupRule(IpProtocol='icmp', FromPort='8', ToPort='-1', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='icmpv6', FromPort='-1', ToPort='-1', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIpv6='::/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIpv6='::/0') ], VpcId=Ref(vpc_id), )) # Create CSS Server instance in the public subnet css_server_instance = template.add_resource( Instance( 'CSSServerInstance', ImageId=Ref(ami_id_linux), InstanceType=Ref(instance_type), KeyName=Ref(keyname), IamInstanceProfile=Ref(iam_role), NetworkInterfaces=[ NetworkInterfaceProperty(GroupSet=[Ref(public_security_group)], AssociatePublicIpAddress='false', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(public_subnet)) ], Tags=Tags(Name=Ref(css_instance_name), Application=ref_stack_id), UserData=Base64( Join('', [ '#!/bin/bash -xe\n', 'echo LC_ALL="en_US.UTF-8" >> /etc/environment\n', 'export LC_ALL="en_US.UTF-8"\n', 'apt-get update\n', 'apt-get -y install python-minimal\n', 'echo -e "import sys\nreload(sys)\nsys.setdefaultencoding(\'utf8\')" > /usr/local/lib/python2.7/dist-packages/setEncoding.py\n' 'echo PYTHONSTARTUP=/usr/local/lib/python2.7/dist-packages/setEncoding.py >> /etc/environment\n', 'export PYTHONSTARTUP=/usr/local/lib/python2.7/dist-packages/setEncoding.py\n', 'curl https://bootstrap.pypa.io/get-pip.py > /tmp/get-pip.py\n', 'python /tmp/get-pip.py\n', 'pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n', '/usr/local/bin/cfn-init -v ', ' --stack ', ref_stack_name, ' --resource CSSServerInstance ', ' --region ', ref_region, '\n' ])), Metadata=Metadata( Authentication({ "S3AccessCreds": AuthenticationBlock(type="S3", accessKeyId=Ref(aws_access_key), secretKey=Ref(aws_secret_key), buckets=Ref(bucket_name)) }), Init({ "config": InitConfig( sources={ '/tmp/mods': Ref(css_mods_tgz), }, files={ '/tmp/init-config.sh': { 'source': Ref(css_init_config_script), 'authentication': 'S3AccessCreds', 'mode': '000755', 'owner': 'root', 'group': 'root' }, '/tmp/css-install-script.sh': { 'source': Ref(css_install_script), 'authentication': 'S3AccessCreds', 'mode': '000755', 'owner': 'root', 'group': 'root' }, '/tmp/cfg/mapcycle.txt': { 'source': Ref(css_mapcycle_txt), 'authentication': 'S3AccessCreds' }, '/tmp/cfg/server.cfg': { 'source': Ref(css_server_cfg), 'authentication': 'S3AccessCreds' } }, commands={ '1_run_init-config.sh': { 'command': '/tmp/init-config.sh', 'cwd': '~', 'env': { 'RCON_PASSWORD': Ref(css_rcon_password) } } }, ) })))) css_server_instance_ip_address = template.add_resource( EIP('IPAddress', Domain='vpc', InstanceId=Ref(css_server_instance))) template.add_output( Output( 'InstanceIp', Value=Ref(css_server_instance_ip_address), Description='Linux Instance IP', )) return template
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"), ))
def main(): '''Function: Generates the Cloudformation template''' template = Template() template.add_description("Dev Stack") keyname_param = template.add_parameter( Parameter( 'KeyName', Description='An existing EC2 KeyPair.', ConstraintDescription='An existing EC2 KeyPair.', Type='AWS::EC2::KeyPair::KeyName', )) db_pass_param = template.add_parameter( Parameter( 'DBPass', NoEcho=True, Type='String', Description='The database admin account password', ConstraintDescription='Must contain only alphanumeric characters', AllowedPattern="[-_a-zA-Z0-9]*", )) db_name_param = template.add_parameter( Parameter( 'DBName', Default='miramax', Type='String', Description='The database name', ConstraintDescription= 'Must begin with a letter and contain only alphanumeric characters', AllowedPattern="[-_a-zA-Z0-9]*", )) db_user_param = template.add_parameter( Parameter( 'DBUser', Default='miramax', Type='String', Description='Username for MySQL database access', ConstraintDescription= 'Must begin with a letter and contain only alphanumeric characters', AllowedPattern="[-_a-zA-Z0-9]*", )) template.add_mapping( 'RegionMap', { 'ap-south-1': { 'ami': 'ami-ee8ea481' }, 'eu-west-3': { 'ami': 'ami-daf040a7' }, 'eu-west-2': { 'ami': 'ami-ddb950ba' }, 'eu-west-1': { 'ami': 'ami-d2414e38' }, 'ap-northeast-2': { 'ami': 'ami-65d86d0b' }, 'ap-northeast-1': { 'ami': 'ami-e875a197' }, 'sa-east-1': { 'ami': 'ami-ccd48ea0' }, 'ca-central-1': { 'ami': 'ami-c3e567a7' }, 'ap-southeast-1': { 'ami': 'ami-31e7e44d' }, 'ap-southeast-2': { 'ami': 'ami-23c51c41' }, 'eu-central-1': { 'ami': 'ami-3c635cd7' }, 'us-east-1': { 'ami': 'ami-5cc39523' }, 'us-east-2': { 'ami': 'ami-67142d02' }, 'us-west-1': { 'ami': 'ami-d7b355b4' }, 'us-west-2': { 'ami': 'ami-39c28c41' } }) ec2_security_group = template.add_resource( ec2.SecurityGroup( 'EC2SecurityGroup', Tags=[ { 'Key': 'Name', 'Value': Ref('AWS::StackName') }, ], GroupDescription='EC2 Security Group', SecurityGroupIngress=[ ec2.SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='0.0.0.0/0', Description='SSH'), ec2.SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0', Description='HTTP'), ec2.SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0', Description='HTTPS'), ], )) db_security_group = template.add_resource( ec2.SecurityGroup('DBSecurityGroup', Tags=[ { 'Key': 'Name', 'Value': Ref('AWS::StackName') }, ], GroupDescription='DB Security Group', SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol='tcp', FromPort='3306', ToPort='3306', SourceSecurityGroupId=GetAtt( ec2_security_group, "GroupId"), Description='MySQL'), ])) ec2_instance = template.add_resource( ec2.Instance( 'Instance', Metadata=Metadata( Init({ "config": InitConfig(files=InitFiles({ "/tmp/instance.txt": InitFile(content=Ref('AWS::StackName'), mode="000644", owner="root", group="root") }), ) }), ), CreationPolicy=CreationPolicy(ResourceSignal=ResourceSignal( Timeout='PT15M')), Tags=[ { 'Key': 'Name', 'Value': Ref('AWS::StackName') }, ], ImageId=FindInMap('RegionMap', Ref('AWS::Region'), 'ami'), InstanceType='t2.micro', KeyName=Ref(keyname_param), SecurityGroups=[Ref(ec2_security_group), Ref(db_security_group)], DependsOn='Database', UserData=Base64( Join('', [ '#!/bin/bash -x\n', 'exec > /tmp/user-data.log 2>&1\n', 'unset UCF_FORCE_CONFFOLD\n', 'export UCF_FORCE_CONFFNEW=YES\n', 'ucf --purge /boot/grub/menu.lst\n', 'export DEBIAN_FRONTEND=noninteractive\n', 'apt-get update\n', 'apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy upgrade\n', 'apt-get install -y python-pip apache2 libapache2-mod-wsgi\n', 'pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n', '# Signal Cloudformation when set up is complete\n', '/usr/local/bin/cfn-signal -e $? --resource=Instance --region=', Ref('AWS::Region'), ' --stack=', Ref('AWS::StackName'), '\n', ])))) ip_association = template.add_resource( ec2.EIPAssociation('IPAssociation', InstanceId=Ref(ec2_instance), AllocationId='eipalloc-aa755d96')) db_instance = template.add_resource( DBInstance( 'Database', DBName=Ref(db_name_param), AllocatedStorage=20, DBInstanceClass='db.t2.micro', Engine='MySQL', EngineVersion='5.7.21', MasterUsername=Ref(db_user_param), MasterUserPassword=Ref(db_pass_param), VPCSecurityGroups=[GetAtt(db_security_group, "GroupId")], )) template.add_output([ Output( 'InstanceDnsName', Description='PublicDnsName', Value=GetAtt(ec2_instance, 'PublicDnsName'), ), Output( 'DatabaseDnsName', Description='DBEndpoint', Value=GetAtt(db_instance, 'Endpoint.Address'), ), ]) print(template.to_yaml())
"Enable HTTP access via port 80 locked down to the ELB and SSH access", )) # @alias component @app:@web_group to WebServerASGGroup WebServerGroup = t.add_resource( AutoScalingGroup( "WebServerGroup", DesiredCapacity=Ref(WebServerCapacity), LaunchConfigurationName=Ref("LaunchConfig"), MinSize="1", MaxSize="5", LoadBalancerNames=[Ref("ElasticLoadBalancer")], AvailabilityZones=GetAZs(""), )) init_config = {"config": InitConfig({})} LaunchConfig = t.add_resource( LaunchConfiguration( "LaunchConfig", Metadata=Init(init_config), UserData=Base64( Join("", [ "#!/bin/bash -xe\n", "yum update -y aws-cfn-bootstrap\n", "# Install the files and packages from the metadata\n", "/opt/aws/bin/cfn-init -v ", " --stack ", Ref("AWS::StackName"), " --resource LaunchConfig ", " --region ", Ref("AWS::Region"), "\n", "# Signal the status from cfn-init\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ",
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())