stacco 0.1.10 → 0.1.17
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Dockerfile +10 -0
- data/README.md +5 -0
- data/bin/stacco +126 -17
- data/lib/aws/with-stacco-patches.rb +149 -0
- data/lib/stacco.rb +4 -418
- data/lib/stacco/base.rb +2 -0
- data/lib/stacco/orchestrator.rb +43 -0
- data/lib/stacco/resources.rb +25 -0
- data/lib/stacco/stack.rb +195 -0
- data/lib/stacco/template.rb +209 -0
- data/lib/stacco/template/base.rb +67 -0
- data/lib/stacco/template/old.rb +85 -0
- data/priv/cloud-init/common.after.sh +2 -0
- data/priv/cloud-init/common.before.sh +11 -9
- data/priv/cloud-init/roles/vpn.sh +16 -10
- data/priv/templates/{cloudformation.json.erb.with-proxy-protocol → bexng.rb} +1 -24
- data/priv/templates/cloudformation.json.erb +614 -380
- data/stacco.gemspec +2 -1
- metadata +403 -7
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'stacco/template'
|
2
|
+
|
3
|
+
class Stacco::Template::Base < Stacco::Template
|
4
|
+
def cloudfront_hosted_zone_map
|
5
|
+
{"us-west-2" => {"HostedZoneId" => "Z2FDTNDATAQYW2"}}
|
6
|
+
end
|
7
|
+
|
8
|
+
def ubuntu_daily_ami_map(want_release, *args)
|
9
|
+
wants = [args.include?(:amd64), args.include?(:hvm), args.include?(:instance_store)]
|
10
|
+
ami_map = {}
|
11
|
+
|
12
|
+
doc = Nokogiri::XML.parse(open("https://cloud-images.ubuntu.com/rss/#{want_release}-Daily.xml"))
|
13
|
+
Nokogiri::HTML.parse(doc.xpath("//item").sort_by{ |it| Time.strptime(it.css("pubDate").text, "%a, %b %d %H:%M:%S %Z %Y") }.last.css('description').children[0].text).xpath('//p')[1].children.find_all{ |el| el.text? }[1..-1].each do |ln|
|
14
|
+
region, ami, arch, storage = ln.text.strip.split("\t")
|
15
|
+
is_hvm = storage.include?("hvm")
|
16
|
+
is_instance_store = storage.include?("instance")
|
17
|
+
is_sixtyfourbit = (arch == 'amd64')
|
18
|
+
next unless [is_sixtyfourbit, is_hvm, is_instance_store] == wants
|
19
|
+
|
20
|
+
ami_map[region] = {"AMI" => ami}
|
21
|
+
end
|
22
|
+
|
23
|
+
ami_map
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
super
|
28
|
+
|
29
|
+
mapping [:ec2, :AMIsByRegion], ubuntu_daily_ami_map('trusty', :amd64)
|
30
|
+
mapping [:cloud_front, :hosted_zones_by_region], cloudfront_hosted_zone_map
|
31
|
+
|
32
|
+
parameter StackVar[:domain], :string,
|
33
|
+
min_length: 5,
|
34
|
+
max_length: 256
|
35
|
+
|
36
|
+
parameter StackVar[:environment], :string,
|
37
|
+
allowed_values: [:production, :staging, :development]
|
38
|
+
|
39
|
+
parameter StackVar[:hosted_zone], :string,
|
40
|
+
min_length: 13,
|
41
|
+
max_length: 16,
|
42
|
+
allowed_pattern: /[A-Z0-9]+/
|
43
|
+
|
44
|
+
parameter StackVar[:keypair], :string,
|
45
|
+
min_length: 1,
|
46
|
+
max_length: 256,
|
47
|
+
allowed_pattern: /[-a-z0-9]+/
|
48
|
+
|
49
|
+
parameter Var[:ec2, :common_user_data, :before], :string
|
50
|
+
parameter Var[:ec2, :common_user_data, :after], :string
|
51
|
+
|
52
|
+
vpc = resource Type[:ec2, :vpc],
|
53
|
+
cidr_block: '10.100.0.0/16',
|
54
|
+
instance_tenancy: 'default',
|
55
|
+
enable_dns_support: true,
|
56
|
+
enable_dns_hostnames: true
|
57
|
+
|
58
|
+
internet_gateway = resource Type[:ec2, :internet_gateway]
|
59
|
+
|
60
|
+
dhcp_options = resource Type[:ec2, :dhcp_options],
|
61
|
+
domain_name: StackVar[:domain],
|
62
|
+
domain_name_servers: [:amazon_provided_dns]
|
63
|
+
|
64
|
+
attach vpc, internet_gateway
|
65
|
+
attach vpc, dhcp_options
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'base64'
|
3
|
+
require 'shellwords'
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
require 'erb'
|
7
|
+
|
8
|
+
require 'stacco/template'
|
9
|
+
|
10
|
+
class Stacco::Template::Old
|
11
|
+
class RenderContext < OpenStruct
|
12
|
+
def initialize(stack, config, vars)
|
13
|
+
@stack = stack
|
14
|
+
@config = config
|
15
|
+
super(vars)
|
16
|
+
end
|
17
|
+
|
18
|
+
def j(str)
|
19
|
+
str.to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
def ja(indent_n, lns)
|
23
|
+
indent = " " * indent_n
|
24
|
+
newline = "\n".to_json
|
25
|
+
lns.map do |ln|
|
26
|
+
if ln.chomp.empty?
|
27
|
+
"%s \n" % [indent]
|
28
|
+
else
|
29
|
+
"%s%s, %s,\n" % [indent, ln.chomp.to_json, newline]
|
30
|
+
end
|
31
|
+
end.join[indent_n .. -3]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def udscript(roles, vars)
|
36
|
+
roles = roles.map{ |role| role.intern }
|
37
|
+
|
38
|
+
unless roles.include? :backend
|
39
|
+
vars = vars.dup
|
40
|
+
vars.delete 'wallet_data'
|
41
|
+
end
|
42
|
+
|
43
|
+
lns = []
|
44
|
+
lns.concat(vars.map do |k, v|
|
45
|
+
var_val = v.include?("\0") ? Base64.encode64(v) : v
|
46
|
+
"export #{k.to_s.upcase}=#{Shellwords.escape(var_val)}\n"
|
47
|
+
end)
|
48
|
+
lns.concat Stacco::Resources::CloudInit::CommonScripts[:before]
|
49
|
+
roles.each{ |role| lns.concat Stacco::Resources::CloudInit::RoleScripts[role] }
|
50
|
+
lns.concat Stacco::Resources::CloudInit::CommonScripts[:after]
|
51
|
+
lns
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_json(opts = {})
|
58
|
+
@stack = opts.delete(:stack)
|
59
|
+
@template_body = @stack.cloudformation_template_body
|
60
|
+
|
61
|
+
vars = @stack.config
|
62
|
+
|
63
|
+
cloudformation_vars = {}
|
64
|
+
cloudformation_vars.update vars
|
65
|
+
cloudformation_vars.update vars['cloudformation']
|
66
|
+
|
67
|
+
cloudinit_vars = {}
|
68
|
+
cloudinit_vars.update vars
|
69
|
+
cloudinit_vars.update vars['cloud-init']
|
70
|
+
cloudinit_vars.each do |k, v|
|
71
|
+
cloudinit_vars.delete(k) if v.kind_of?(Hash) or v.kind_of?(Array)
|
72
|
+
end
|
73
|
+
|
74
|
+
cloudformation_vars['userdata'] = {}
|
75
|
+
cloudformation_vars['roles'].each do |host_name, host_roles|
|
76
|
+
cloudformation_vars['userdata'][host_name] = udscript(host_roles, cloudinit_vars)
|
77
|
+
end
|
78
|
+
|
79
|
+
cloudformation_vars['userdata_before_script'] = Stacco::Resources::CloudInit::CommonScripts[:before]
|
80
|
+
cloudformation_vars['userdata_after_script'] = Stacco::Resources::CloudInit::CommonScripts[:after]
|
81
|
+
|
82
|
+
b = RenderContext.new(@stack, vars, cloudformation_vars).instance_eval{ binding }
|
83
|
+
ERB.new(@template_body).result(b)
|
84
|
+
end
|
85
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# hit aws bootstrapping webhook
|
2
|
+
if [ -n "${AWS_WAIT_HANDLE}" ]; then
|
2
3
|
unique_id=$(uuidgen -t)
|
3
4
|
|
4
5
|
aws_wait_handle_response_file="/tmp/cf-wait-handle-response.json"
|
@@ -13,5 +14,6 @@ EOF
|
|
13
14
|
|
14
15
|
curl -s -T "${aws_wait_handle_response_file}" "${AWS_WAIT_HANDLE}"
|
15
16
|
rm "${aws_wait_handle_response_file}"
|
17
|
+
fi
|
16
18
|
|
17
19
|
echo "done bootstrapping!"
|
@@ -1,21 +1,23 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# ensure the nat is up before configuring
|
2
|
+
while true; do
|
3
|
+
nat_status=$(curl -s -o /dev/null -I -w "%{http_code}" -m 2 http://bex-status.s3.amazonaws.com/status.json)
|
4
|
+
if [ "${nat_status}" = "200" ]; then
|
5
|
+
break
|
6
|
+
fi
|
7
|
+
sleep 2
|
6
8
|
done
|
7
9
|
|
8
|
-
|
10
|
+
|
11
|
+
# configure hostname from metadata service
|
9
12
|
private_hostname=$(curl http://169.254.169.254/latest/meta-data/hostname)
|
13
|
+
echo "${private_hostname}" > /etc/hostname
|
10
14
|
|
11
|
-
echo "${public_hostname}" > /etc/hostname
|
12
15
|
hostname -b -F /etc/hostname
|
13
|
-
|
14
16
|
short_hostname=$(hostname -s)
|
15
17
|
|
16
18
|
sed -i '/127\.0\.0\.1/d' /etc/hosts
|
17
19
|
cat >>/etc/hosts <<EOF
|
18
|
-
127.0.0.1 localhost ${short_hostname} ${
|
20
|
+
127.0.0.1 localhost ${short_hostname} ${private_hostname}
|
19
21
|
EOF
|
20
22
|
|
21
23
|
|
@@ -37,14 +37,14 @@ cat >"/usr/local/openvpn_as/etc/config.json" <<EOF
|
|
37
37
|
"admin_ui.https.ip_address": "eth0",
|
38
38
|
"admin_ui.https.port": "943",
|
39
39
|
"aui.eula_version": "2",
|
40
|
-
"auth.ldap.0.name": "My LDAP
|
40
|
+
"auth.ldap.0.name": "My LDAP Servers",
|
41
41
|
"auth.ldap.0.ssl_verify": "never",
|
42
42
|
"auth.ldap.0.timeout": "4",
|
43
43
|
"auth.ldap.0.use_ssl": "never",
|
44
44
|
"auth.module.type": "pam",
|
45
45
|
"auth.pam.0.service": "openvpnas",
|
46
46
|
"auth.radius.0.acct_enable": "false",
|
47
|
-
"auth.radius.0.name": "My Radius
|
47
|
+
"auth.radius.0.name": "My Radius Servers",
|
48
48
|
"cs.cws_proto_v2": "true",
|
49
49
|
"cs.https.ip_address": "eth0",
|
50
50
|
"cs.https.port": "943",
|
@@ -52,35 +52,41 @@ cat >"/usr/local/openvpn_as/etc/config.json" <<EOF
|
|
52
52
|
"host.name": "vpn.${DOMAIN}",
|
53
53
|
"sa.initial_run_groups.0": "web_group",
|
54
54
|
"sa.initial_run_groups.1": "openvpn_group",
|
55
|
+
"vpn.client.config_text": "",
|
55
56
|
"vpn.client.routing.inter_client": "false",
|
56
57
|
"vpn.client.routing.reroute_dns": "true",
|
57
58
|
"vpn.client.routing.reroute_gw": "false",
|
58
|
-
"vpn.daemon.0.client.netmask_bits": "
|
59
|
-
"vpn.daemon.0.client.network": "
|
59
|
+
"vpn.daemon.0.client.netmask_bits": "24",
|
60
|
+
"vpn.daemon.0.client.network": "10.0.23.0",
|
60
61
|
"vpn.daemon.0.listen.ip_address": "eth0",
|
61
62
|
"vpn.daemon.0.listen.port": "443",
|
62
63
|
"vpn.daemon.0.listen.protocol": "tcp",
|
63
64
|
"vpn.daemon.0.server.ip_address": "eth0",
|
65
|
+
"vpn.general.osi_layer": "3",
|
66
|
+
"vpn.server.config_text": "",
|
64
67
|
"vpn.server.daemon.enable": "true",
|
65
|
-
"vpn.server.daemon.tcp.n_daemons": 1,
|
68
|
+
"vpn.server.daemon.tcp.n_daemons": "1",
|
66
69
|
"vpn.server.daemon.tcp.port": "443",
|
67
|
-
"vpn.server.daemon.udp.n_daemons": 1,
|
70
|
+
"vpn.server.daemon.udp.n_daemons": "1",
|
68
71
|
"vpn.server.daemon.udp.port": "1194",
|
69
|
-
"vpn.server.
|
72
|
+
"vpn.server.duplicate_cn": "true",
|
73
|
+
"vpn.server.group_pool.0": "10.0.23.0/24",
|
70
74
|
"vpn.server.port_share.enable": "true",
|
71
75
|
"vpn.server.port_share.ip_address": "1.2.3.4",
|
72
76
|
"vpn.server.port_share.port": "1234",
|
73
77
|
"vpn.server.port_share.service": "admin+client",
|
78
|
+
"vpn.server.routing.allow_private_nets_to_clients": "true",
|
74
79
|
"vpn.server.routing.gateway_access": "true",
|
75
80
|
"vpn.server.routing.private_access": "nat",
|
76
|
-
"vpn.server.routing.private_network.0": "10.
|
77
|
-
"vpn.server.routing.private_network.1": "10.
|
81
|
+
"vpn.server.routing.private_network.0": "10.0.0.0/24",
|
82
|
+
"vpn.server.routing.private_network.1": "10.0.1.0/24",
|
78
83
|
"vpn.tls_refresh.do_reauth": "true",
|
79
84
|
"vpn.tls_refresh.interval": "360"
|
80
85
|
},
|
81
86
|
"_INTERNAL": {
|
82
87
|
"run_api.active_profile": "Default",
|
83
|
-
"webui.edit_profile": "Default"
|
88
|
+
"webui.edit_profile": "Default",
|
89
|
+
"webui.welcome_shown": "true"
|
84
90
|
}
|
85
91
|
}
|
86
92
|
EOF
|
@@ -1,13 +1,4 @@
|
|
1
|
-
|
2
|
-
ubuntu_daily_ami = "ami-6ac2a85a"
|
3
|
-
docker_library_snapshot = "snap-d37e4721"
|
4
|
-
%>
|
5
|
-
|
6
|
-
{
|
7
|
-
"AWSTemplateFormatVersion": "2010-09-09",
|
8
|
-
"Description": <%= j @stack.description %>,
|
9
|
-
|
10
|
-
"Resources": {
|
1
|
+
class Stacco::Template::BexNG < Stacco::Template::Base
|
11
2
|
|
12
3
|
"VPC": {"Type": "AWS::EC2::VPC", "Properties": {
|
13
4
|
"CidrBlock": "10.100.0.0/16",
|
@@ -320,13 +311,6 @@
|
|
320
311
|
"arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":server-certificate/",
|
321
312
|
<%= j frontend_cert_path %>, ".pem"
|
322
313
|
]]}
|
323
|
-
}],
|
324
|
-
|
325
|
-
"Policies": [{
|
326
|
-
"PolicyName": "EnableProxyProtocol",
|
327
|
-
"PolicyType": "ProxyProtocolPolicyType",
|
328
|
-
"Attributes": [{"Name": "ProxyProtocol", "Value": "true"}],
|
329
|
-
"InstancePorts": ["80"]
|
330
314
|
}]
|
331
315
|
}},
|
332
316
|
|
@@ -437,13 +421,6 @@
|
|
437
421
|
"arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":server-certificate/",
|
438
422
|
<%= j backend_cert_path %>, ".pem"
|
439
423
|
]]}
|
440
|
-
}],
|
441
|
-
|
442
|
-
"Policies": [{
|
443
|
-
"PolicyName": "EnableProxyProtocol",
|
444
|
-
"PolicyType": "ProxyProtocolPolicyType",
|
445
|
-
"Attributes": [{"Name": "ProxyProtocol", "Value": "true"}],
|
446
|
-
"InstancePorts": ["80"]
|
447
424
|
}]
|
448
425
|
}},
|
449
426
|
|
@@ -1,313 +1,453 @@
|
|
1
1
|
<%
|
2
2
|
ubuntu_daily_ami = "ami-6ac2a85a"
|
3
3
|
docker_library_snapshot = "snap-d37e4721"
|
4
|
+
layers_enabled = Set[:bastion, :instances, :api, :static]
|
4
5
|
%>
|
5
6
|
|
6
7
|
{
|
7
|
-
"AWSTemplateFormatVersion": "2010-09-09",
|
8
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
8
9
|
"Description": <%= j @stack.description %>,
|
9
10
|
|
10
|
-
"
|
11
|
-
|
12
|
-
|
13
|
-
"
|
14
|
-
"
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
"
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
"
|
24
|
-
"
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
}},
|
30
|
-
|
31
|
-
"PublicSubnet": {"Type": "AWS::EC2::Subnet", "Properties": {
|
32
|
-
"VpcId": {"Ref": "VPC"},
|
33
|
-
"CidrBlock": "10.100.0.0/24"
|
34
|
-
}},
|
35
|
-
"PublicSubnetAcl": {"Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": {
|
36
|
-
"NetworkAclId": {"Ref": "NetworkAcl"},
|
37
|
-
"SubnetId": {"Ref": "PublicSubnet"}
|
38
|
-
}},
|
39
|
-
"PublicRouteTable": {"Type": "AWS::EC2::RouteTable", "Properties": {
|
40
|
-
"VpcId": {"Ref": "VPC"}
|
41
|
-
}},
|
42
|
-
"PublicSubnetRoute": {"Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": {
|
43
|
-
"SubnetId": {"Ref": "PublicSubnet"},
|
44
|
-
"RouteTableId": {"Ref": "PublicRouteTable"}
|
45
|
-
}},
|
46
|
-
"PublicSubnetGatewayRoute": {"Type": "AWS::EC2::Route", "DependsOn": "InternetGatewayAttachment", "Properties": {
|
47
|
-
"DestinationCidrBlock": "0.0.0.0/0",
|
48
|
-
"RouteTableId": {"Ref": "PublicRouteTable"},
|
49
|
-
"GatewayId": {"Ref": "InternetGateway"}
|
50
|
-
}},
|
51
|
-
"PublicIngressAcl": {"Type": "AWS::EC2::NetworkAclEntry", "Properties": {
|
52
|
-
"NetworkAclId": {"Ref": "NetworkAcl"},
|
53
|
-
"RuleNumber": "100",
|
54
|
-
|
55
|
-
"CidrBlock": "0.0.0.0/0",
|
56
|
-
"Protocol": "-1",
|
57
|
-
"RuleAction": "allow"
|
58
|
-
}},
|
59
|
-
"PublicEgressAcl": {"Type": "AWS::EC2::NetworkAclEntry", "Properties": {
|
60
|
-
"NetworkAclId": {"Ref": "NetworkAcl"},
|
61
|
-
"RuleNumber": "100",
|
62
|
-
|
63
|
-
"Egress": true,
|
64
|
-
"CidrBlock": "0.0.0.0/0",
|
65
|
-
"Protocol": "-1",
|
66
|
-
"RuleAction": "allow"
|
67
|
-
}},
|
11
|
+
"Parameters" : {
|
12
|
+
"NATInstanceType" : {
|
13
|
+
"Description" : "NAT Device EC2 instance type",
|
14
|
+
"Type" : "String",
|
15
|
+
"Default" : "m3.medium"
|
16
|
+
}
|
17
|
+
},
|
18
|
+
|
19
|
+
"Mappings" : {
|
20
|
+
"AWSNATAMI" : {
|
21
|
+
"us-east-1" : { "AMI" : "ami-c6699baf" },
|
22
|
+
"us-west-2" : { "AMI" : "ami-52ff7262" },
|
23
|
+
"us-west-1" : { "AMI" : "ami-3bcc9e7e" },
|
24
|
+
"eu-west-1" : { "AMI" : "ami-0b5b6c7f" },
|
25
|
+
"ap-southeast-1" : { "AMI" : "ami-02eb9350" },
|
26
|
+
"ap-southeast-2" : { "AMI" : "ami-ab990e91" },
|
27
|
+
"ap-northeast-1" : { "AMI" : "ami-14d86d15" },
|
28
|
+
"sa-east-1" : { "AMI" : "ami-0439e619" }
|
29
|
+
},
|
68
30
|
|
69
|
-
"
|
70
|
-
"
|
71
|
-
"
|
72
|
-
"
|
73
|
-
}
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
"
|
79
|
-
"
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
}
|
31
|
+
"SubnetConfig" : {
|
32
|
+
"VPC" : { "CIDR" : "10.0.0.0/16" },
|
33
|
+
"Public" : { "CIDR" : "10.0.0.0/24" },
|
34
|
+
"Private" : { "CIDR" : "10.0.1.0/24" }
|
35
|
+
}
|
36
|
+
},
|
37
|
+
|
38
|
+
"Resources" : {
|
39
|
+
|
40
|
+
"VPC" : {
|
41
|
+
"Type" : "AWS::EC2::VPC",
|
42
|
+
"Properties" : {
|
43
|
+
"CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]},
|
44
|
+
"EnableDnsSupport": "true",
|
45
|
+
"EnableDnsHostnames": "true",
|
46
|
+
"Tags" : [
|
47
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
48
|
+
{ "Key" : "Network", "Value" : "Public" }
|
49
|
+
]
|
50
|
+
}
|
51
|
+
},
|
90
52
|
|
91
53
|
"DHCPOptions": {"Type": "AWS::EC2::DHCPOptions", "Properties": {
|
92
54
|
"DomainName": <%= j domain %>,
|
93
55
|
"DomainNameServers": ["AmazonProvidedDNS"]
|
94
56
|
}},
|
57
|
+
|
95
58
|
"VPCDHCPOptionsAssociation": {"Type": "AWS::EC2::VPCDHCPOptionsAssociation", "Properties": {
|
96
59
|
"VpcId": {"Ref": "VPC"},
|
97
60
|
"DhcpOptionsId": {"Ref": "DHCPOptions"}
|
98
61
|
}},
|
99
62
|
|
63
|
+
"PublicSubnet" : {
|
64
|
+
"Type" : "AWS::EC2::Subnet",
|
65
|
+
"Properties" : {
|
66
|
+
"VpcId" : { "Ref" : "VPC" },
|
67
|
+
"CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "Public", "CIDR" ]},
|
68
|
+
"Tags" : [
|
69
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
70
|
+
{ "Key" : "Network", "Value" : "Public" }
|
71
|
+
]
|
72
|
+
}
|
73
|
+
},
|
100
74
|
|
75
|
+
"InternetGateway" : {
|
76
|
+
"Type" : "AWS::EC2::InternetGateway",
|
77
|
+
"Properties" : {
|
78
|
+
"Tags" : [
|
79
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
80
|
+
{ "Key" : "Network", "Value" : "Public" }
|
81
|
+
]
|
82
|
+
}
|
83
|
+
},
|
101
84
|
|
85
|
+
"GatewayToInternet" : {
|
86
|
+
"Type" : "AWS::EC2::VPCGatewayAttachment",
|
87
|
+
"Properties" : {
|
88
|
+
"VpcId" : { "Ref" : "VPC" },
|
89
|
+
"InternetGatewayId" : { "Ref" : "InternetGateway" }
|
90
|
+
}
|
91
|
+
},
|
102
92
|
|
93
|
+
"PublicRouteTable" : {
|
94
|
+
"Type" : "AWS::EC2::RouteTable",
|
95
|
+
"Properties" : {
|
96
|
+
"VpcId" : { "Ref" : "VPC" },
|
97
|
+
"Tags" : [
|
98
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
99
|
+
{ "Key" : "Network", "Value" : "Public" }
|
100
|
+
]
|
101
|
+
}
|
102
|
+
},
|
103
103
|
|
104
|
+
"PublicRoute" : {
|
105
|
+
"Type" : "AWS::EC2::Route",
|
106
|
+
"Properties" : {
|
107
|
+
"RouteTableId" : { "Ref" : "PublicRouteTable" },
|
108
|
+
"DestinationCidrBlock" : "0.0.0.0/0",
|
109
|
+
"GatewayId" : { "Ref" : "InternetGateway" }
|
110
|
+
}
|
111
|
+
},
|
104
112
|
|
105
|
-
|
106
|
-
|
107
|
-
"
|
108
|
-
|
109
|
-
|
110
|
-
"IndexDocument": "index.html",
|
111
|
-
"ErrorDocument": "404.html"
|
113
|
+
"PublicSubnetRouteTableAssociation" : {
|
114
|
+
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
|
115
|
+
"Properties" : {
|
116
|
+
"SubnetId" : { "Ref" : "PublicSubnet" },
|
117
|
+
"RouteTableId" : { "Ref" : "PublicRouteTable" }
|
112
118
|
}
|
113
|
-
}
|
119
|
+
},
|
114
120
|
|
115
|
-
"
|
116
|
-
"
|
117
|
-
|
118
|
-
"
|
121
|
+
"PublicNetworkAcl" : {
|
122
|
+
"Type" : "AWS::EC2::NetworkAcl",
|
123
|
+
"Properties" : {
|
124
|
+
"VpcId" : { "Ref" : "VPC" },
|
125
|
+
"Tags" : [
|
126
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
127
|
+
{ "Key" : "Network", "Value" : "Public" }
|
128
|
+
]
|
129
|
+
}
|
130
|
+
},
|
119
131
|
|
120
|
-
|
121
|
-
|
122
|
-
|
132
|
+
"InboundHTTPPublicNetworkAclEntry" : {
|
133
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
134
|
+
"Properties" : {
|
135
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
136
|
+
"RuleNumber" : "100",
|
137
|
+
"Protocol" : "6",
|
138
|
+
"RuleAction" : "allow",
|
139
|
+
"Egress" : "false",
|
140
|
+
"CidrBlock" : "0.0.0.0/0",
|
141
|
+
"PortRange" : { "From" : "80", "To" : "80" }
|
142
|
+
}
|
143
|
+
},
|
123
144
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
145
|
+
"InboundHTTPSPublicNetworkAclEntry" : {
|
146
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
147
|
+
"Properties" : {
|
148
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
149
|
+
"RuleNumber" : "101",
|
150
|
+
"Protocol" : "6",
|
151
|
+
"RuleAction" : "allow",
|
152
|
+
"Egress" : "false",
|
153
|
+
"CidrBlock" : "0.0.0.0/0",
|
154
|
+
"PortRange" : { "From" : "443", "To" : "443" }
|
155
|
+
}
|
156
|
+
},
|
130
157
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
158
|
+
"InboundSSHPublicNetworkAclEntry" : {
|
159
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
160
|
+
"Properties" : {
|
161
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
162
|
+
"RuleNumber" : "102",
|
163
|
+
"Protocol" : "6",
|
164
|
+
"RuleAction" : "allow",
|
165
|
+
"Egress" : "false",
|
166
|
+
"CidrBlock" : "0.0.0.0/0",
|
167
|
+
"PortRange" : { "From" : "22", "To" : "22" }
|
136
168
|
}
|
137
|
-
}
|
169
|
+
},
|
138
170
|
|
139
|
-
"
|
140
|
-
"
|
141
|
-
"
|
142
|
-
|
143
|
-
|
144
|
-
"
|
145
|
-
"
|
146
|
-
|
147
|
-
|
171
|
+
"InboundEmphemeralPublicNetworkAclEntry" : {
|
172
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
173
|
+
"Properties" : {
|
174
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
175
|
+
"RuleNumber" : "103",
|
176
|
+
"Protocol" : "6",
|
177
|
+
"RuleAction" : "allow",
|
178
|
+
"Egress" : "false",
|
179
|
+
"CidrBlock" : "0.0.0.0/0",
|
180
|
+
"PortRange" : { "From" : "1024", "To" : "65535" }
|
181
|
+
}
|
182
|
+
},
|
148
183
|
|
149
|
-
"
|
150
|
-
"
|
151
|
-
"
|
152
|
-
|
153
|
-
"
|
154
|
-
|
155
|
-
|
156
|
-
|
184
|
+
"InboundVPNAccessPublicNetworkAclEntry" : {
|
185
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
186
|
+
"Properties" : {
|
187
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
188
|
+
"RuleNumber" : "104",
|
189
|
+
"Protocol" : "-1",
|
190
|
+
"RuleAction" : "allow",
|
191
|
+
"Egress" : "false",
|
192
|
+
"CidrBlock" : "0.0.0.0/0",
|
193
|
+
"PortRange" : { "From" : "1192", "To" : "1194" }
|
157
194
|
}
|
158
|
-
}
|
195
|
+
},
|
159
196
|
|
160
|
-
"
|
161
|
-
"
|
162
|
-
|
163
|
-
"
|
197
|
+
"InboundVPNAdministrationPublicNetworkAclEntry" : {
|
198
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
199
|
+
"Properties" : {
|
200
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
201
|
+
"RuleNumber" : "105",
|
202
|
+
"Protocol" : "-1",
|
203
|
+
"RuleAction" : "allow",
|
204
|
+
"Egress" : "false",
|
205
|
+
"CidrBlock" : "0.0.0.0/0",
|
206
|
+
"PortRange" : { "From" : "943", "To" : "943" }
|
207
|
+
}
|
208
|
+
},
|
164
209
|
|
165
|
-
|
166
|
-
|
167
|
-
|
210
|
+
"OutboundPublicNetworkAclEntry" : {
|
211
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
212
|
+
"Properties" : {
|
213
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
|
214
|
+
"RuleNumber" : "100",
|
215
|
+
"Protocol" : "-1",
|
216
|
+
"RuleAction" : "allow",
|
217
|
+
"Egress" : "true",
|
218
|
+
"CidrBlock" : "0.0.0.0/0",
|
219
|
+
"PortRange" : { "From" : "0", "To" : "65535" }
|
220
|
+
}
|
221
|
+
},
|
168
222
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
223
|
+
"PublicSubnetNetworkAclAssociation" : {
|
224
|
+
"Type" : "AWS::EC2::SubnetNetworkAclAssociation",
|
225
|
+
"Properties" : {
|
226
|
+
"SubnetId" : { "Ref" : "PublicSubnet" },
|
227
|
+
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" }
|
228
|
+
}
|
229
|
+
},
|
175
230
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
}
|
231
|
+
"PrivateSubnet" : {
|
232
|
+
"Type" : "AWS::EC2::Subnet",
|
233
|
+
"Properties" : {
|
234
|
+
"VpcId" : { "Ref" : "VPC" },
|
235
|
+
"AvailabilityZone": {"Fn::GetAtt": ["PublicSubnet", "AvailabilityZone"]},
|
236
|
+
"CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "Private", "CIDR" ]},
|
237
|
+
"Tags" : [
|
238
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
239
|
+
{ "Key" : "Name", "Value" : "Private" }
|
240
|
+
]
|
181
241
|
}
|
182
|
-
}
|
242
|
+
},
|
183
243
|
|
184
|
-
"
|
185
|
-
"
|
186
|
-
"
|
187
|
-
|
188
|
-
|
189
|
-
|
244
|
+
"PrivateRouteTable" : {
|
245
|
+
"Type" : "AWS::EC2::RouteTable",
|
246
|
+
"Properties" : {
|
247
|
+
"VpcId" : { "Ref" : "VPC" },
|
248
|
+
"Tags" : [
|
249
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
250
|
+
{ "Key" : "Network", "Value" : "Private" }
|
251
|
+
]
|
252
|
+
}
|
253
|
+
},
|
190
254
|
|
255
|
+
"PrivateSubnetRouteTableAssociation" : {
|
256
|
+
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
|
257
|
+
"Properties" : {
|
258
|
+
"SubnetId" : { "Ref" : "PrivateSubnet" },
|
259
|
+
"RouteTableId" : { "Ref" : "PrivateRouteTable" }
|
260
|
+
}
|
261
|
+
},
|
191
262
|
|
192
|
-
"
|
193
|
-
"
|
194
|
-
"
|
195
|
-
|
196
|
-
"
|
197
|
-
"
|
263
|
+
"PrivateRoute" : {
|
264
|
+
"Type" : "AWS::EC2::Route",
|
265
|
+
"Properties" : {
|
266
|
+
"RouteTableId" : { "Ref" : "PrivateRouteTable" },
|
267
|
+
"DestinationCidrBlock" : "0.0.0.0/0",
|
268
|
+
"InstanceId" : { "Ref" : "NATDevice" }
|
198
269
|
}
|
199
|
-
}
|
270
|
+
},
|
200
271
|
|
201
|
-
"
|
202
|
-
"
|
203
|
-
|
204
|
-
"
|
272
|
+
"PrivateNetworkAcl" : {
|
273
|
+
"Type" : "AWS::EC2::NetworkAcl",
|
274
|
+
"Properties" : {
|
275
|
+
"VpcId" : { "Ref" : "VPC" },
|
276
|
+
"Tags" : [
|
277
|
+
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
|
278
|
+
{ "Key" : "Network", "Value" : "Private" }
|
279
|
+
]
|
280
|
+
}
|
281
|
+
},
|
205
282
|
|
206
|
-
|
207
|
-
|
208
|
-
|
283
|
+
"InboundPrivateNetworkAclEntry" : {
|
284
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
285
|
+
"Properties" : {
|
286
|
+
"NetworkAclId" : { "Ref" : "PrivateNetworkAcl" },
|
287
|
+
"RuleNumber" : "100",
|
288
|
+
"Protocol" : "-1",
|
289
|
+
"RuleAction" : "allow",
|
290
|
+
"Egress" : "false",
|
291
|
+
"CidrBlock" : "0.0.0.0/0",
|
292
|
+
"PortRange" : { "From" : "0", "To" : "65535" }
|
293
|
+
}
|
294
|
+
},
|
209
295
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
296
|
+
"OutboundPrivateNetworkAclEntry" : {
|
297
|
+
"Type" : "AWS::EC2::NetworkAclEntry",
|
298
|
+
"Properties" : {
|
299
|
+
"NetworkAclId" : { "Ref" : "PrivateNetworkAcl" },
|
300
|
+
"RuleNumber" : "100",
|
301
|
+
"Protocol" : "-1",
|
302
|
+
"RuleAction" : "allow",
|
303
|
+
"Egress" : "true",
|
304
|
+
"CidrBlock" : "0.0.0.0/0",
|
305
|
+
"PortRange" : { "From" : "0", "To" : "65535" }
|
306
|
+
}
|
307
|
+
},
|
216
308
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
}
|
309
|
+
"PrivateSubnetNetworkAclAssociation" : {
|
310
|
+
"Type" : "AWS::EC2::SubnetNetworkAclAssociation",
|
311
|
+
"Properties" : {
|
312
|
+
"SubnetId" : { "Ref" : "PrivateSubnet" },
|
313
|
+
"NetworkAclId" : { "Ref" : "PrivateNetworkAcl" }
|
222
314
|
}
|
223
|
-
}
|
315
|
+
},
|
224
316
|
|
225
|
-
"AdminS3BucketDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
226
|
-
"HostedZoneId": <%= j hosted_zone %>,
|
227
|
-
"Type": "CNAME", "TTL": "300",
|
228
|
-
"Name": <%= j "admin.#{domain}." %>,
|
229
|
-
"ResourceRecords": [{"Fn::GetAtt": ["AdminS3BucketDistribution", "DomainName"]}]
|
230
|
-
}},
|
231
317
|
|
232
318
|
|
233
319
|
|
234
320
|
|
235
|
-
"InstanceBootstrapWaitHandle": {"Type": "AWS::CloudFormation::WaitConditionHandle", "Properties": {}},
|
236
|
-
"InstanceBootstrap": {"Type": "AWS::CloudFormation::WaitCondition", "DependsOn": ["Frontend", "Backend", "OpenVPN"], "Properties": {
|
237
|
-
"Handle": {"Ref": "InstanceBootstrapWaitHandle"},
|
238
|
-
"Count": "3",
|
239
|
-
"Timeout": "6000"
|
240
|
-
}},
|
241
321
|
|
322
|
+
"NATIPAddress" : {
|
323
|
+
"Type" : "AWS::EC2::EIP",
|
324
|
+
"DependsOn" : "GatewayToInternet",
|
325
|
+
"Properties" : {
|
326
|
+
"Domain" : "vpc",
|
327
|
+
"InstanceId" : { "Ref" : "NATDevice" }
|
328
|
+
}
|
329
|
+
},
|
242
330
|
|
331
|
+
"NATDevice" : {
|
332
|
+
"Type" : "AWS::EC2::Instance",
|
333
|
+
"Properties" : {
|
334
|
+
"InstanceType" : { "Ref" : "NATInstanceType" },
|
335
|
+
"SubnetId" : { "Ref" : "PublicSubnet" },
|
336
|
+
"SourceDestCheck" : "false",
|
337
|
+
"ImageId" : { "Fn::FindInMap" : [ "AWSNATAMI", { "Ref" : "AWS::Region" }, "AMI" ]},
|
338
|
+
"SecurityGroupIds" : [{ "Ref" : "NATSecurityGroup" }],
|
243
339
|
|
244
|
-
|
245
|
-
|
246
|
-
|
340
|
+
"UserData": {"Fn::Base64": {"Fn::Join": ["", [
|
341
|
+
"#!/bin/bash -e\n",
|
342
|
+
"export AWS_WAIT_HANDLE='", {"Ref": "NATDeviceConfigurationWaitHandle"}, "'\n",
|
343
|
+
<%= ja 8, userdata_after_script %>
|
344
|
+
]]}}
|
345
|
+
}
|
346
|
+
},
|
247
347
|
|
248
|
-
|
249
|
-
{ "Key": "Name", "Value": "web01" },
|
250
|
-
{ "Key": "Environment", "Value": <%= j environment %> }
|
251
|
-
],
|
348
|
+
"NATDeviceConfigurationWaitHandle": {"Type": "AWS::CloudFormation::WaitConditionHandle", "Properties": {}},
|
252
349
|
|
253
|
-
|
350
|
+
"NATDeviceConfiguration": {"Type": "AWS::CloudFormation::WaitCondition", "DependsOn": ["NATDevice"], "Properties": {
|
351
|
+
"Handle": {"Ref": "NATDeviceConfigurationWaitHandle"},
|
352
|
+
"Count": "1",
|
353
|
+
"Timeout": "1200"
|
354
|
+
}},
|
254
355
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
}
|
260
|
-
|
356
|
+
"NATSecurityGroup" : {
|
357
|
+
"Type" : "AWS::EC2::SecurityGroup",
|
358
|
+
"Properties" : {
|
359
|
+
"GroupDescription" : "Enable internal access to the NAT device",
|
360
|
+
"VpcId" : { "Ref" : "VPC" },
|
361
|
+
"SecurityGroupIngress" : [
|
362
|
+
{"IpProtocol": "-1", "FromPort": "0", "ToPort": "65535", "CidrIp": "0.0.0.0/0"}
|
363
|
+
],
|
364
|
+
"SecurityGroupEgress" : [
|
365
|
+
{"IpProtocol": "-1", "FromPort": "0", "ToPort": "65535", "CidrIp": "0.0.0.0/0"}
|
366
|
+
]
|
367
|
+
}
|
368
|
+
},
|
261
369
|
|
262
|
-
"NetworkInterfaces": [{
|
263
|
-
"Description": "Primary network interface",
|
264
|
-
"DeviceIndex": 0,
|
265
|
-
"DeleteOnTermination": true,
|
266
370
|
|
371
|
+
<% if layers_enabled.member? :bastion %>
|
372
|
+
"BastionInstanceSecurityGroup" : {
|
373
|
+
"Type" : "AWS::EC2::SecurityGroup",
|
374
|
+
"Properties" : {
|
375
|
+
"GroupDescription" : "Allow the application instances to access the NAT device",
|
376
|
+
"VpcId" : { "Ref" : "VPC" },
|
377
|
+
|
378
|
+
"SecurityGroupIngress": [
|
379
|
+
{"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0"},
|
380
|
+
{"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "CidrIp": "0.0.0.0/0"},
|
381
|
+
{"IpProtocol": "udp", "FromPort": "1192", "ToPort": "1194", "CidrIp": "0.0.0.0/0"},
|
382
|
+
{"IpProtocol": "tcp", "FromPort": "943", "ToPort": "943", "CidrIp": "0.0.0.0/0"},
|
383
|
+
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0"}
|
384
|
+
],
|
385
|
+
"SecurityGroupEgress": [
|
386
|
+
{"IpProtocol": "-1", "CidrIp": "0.0.0.0/0"}
|
387
|
+
]
|
388
|
+
}
|
389
|
+
},
|
390
|
+
|
391
|
+
"BastionInstance" : {
|
392
|
+
"Type" : "AWS::EC2::Instance",
|
393
|
+
"Properties" : {
|
394
|
+
"InstanceType": "m1.small",
|
395
|
+
"ImageId": <%= j ubuntu_daily_ami %>,
|
396
|
+
"SourceDestCheck": "false",
|
397
|
+
|
398
|
+
"NetworkInterfaces": [{
|
399
|
+
"DeviceIndex": "0",
|
400
|
+
"AssociatePublicIpAddress": "true",
|
401
|
+
"DeleteOnTermination": "true",
|
267
402
|
"SubnetId": {"Ref": "PublicSubnet"},
|
268
|
-
"GroupSet": [{"Ref": "
|
269
|
-
|
403
|
+
"GroupSet" : [{"Ref" : "BastionInstanceSecurityGroup"}]
|
404
|
+
}],
|
270
405
|
|
271
|
-
|
272
|
-
"
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
406
|
+
"KeyName": <%= j @stack.iam_keypair_name %>,
|
407
|
+
"UserData": {"Fn::Base64": {"Fn::Join": ["", [
|
408
|
+
"#!/bin/bash -e\n",
|
409
|
+
<%= ja 8, userdata['bastion'] %>
|
410
|
+
]]}}
|
411
|
+
}
|
412
|
+
},
|
413
|
+
|
414
|
+
"BastionDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
415
|
+
"HostedZoneId": <%= j hosted_zone %>,
|
416
|
+
"Type": "CNAME", "TTL": "300",
|
417
|
+
"Name": <%= j "vpn.#{domain}." %>,
|
418
|
+
"ResourceRecords": [{"Fn::GetAtt": ["BastionInstance", "PublicDnsName"]}]
|
277
419
|
}},
|
420
|
+
<% end %>
|
421
|
+
|
422
|
+
|
423
|
+
|
278
424
|
|
279
|
-
|
280
|
-
|
425
|
+
|
426
|
+
|
427
|
+
<% if layers_enabled.member? :api %>
|
428
|
+
"ClientAPISecurityGroup": {"Type": "AWS::EC2::SecurityGroup", "Properties": {
|
429
|
+
"GroupDescription": "Frontend API security group",
|
281
430
|
"VpcId": {"Ref": "VPC"},
|
282
431
|
|
283
432
|
"SecurityGroupIngress": [
|
284
|
-
{"IpProtocol": "tcp", "FromPort": "
|
285
|
-
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": <%= j bastion_ssh_cidr %>},
|
286
|
-
{"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "10.100.0.0/24"}
|
433
|
+
{"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "CidrIp": "0.0.0.0/0"}
|
287
434
|
],
|
288
|
-
"SecurityGroupEgress": [
|
289
|
-
|
290
|
-
|
291
|
-
"FrontendEIP": {"Type": "AWS::EC2::EIP", "Properties": {
|
292
|
-
"Domain": "VPC"
|
293
|
-
}},
|
294
|
-
|
295
|
-
"FrontendEIPAssociation": {"Type": "AWS::EC2::EIPAssociation", "Properties": {
|
296
|
-
"AllocationId": {"Fn::GetAtt": ["FrontendEIP", "AllocationId"]},
|
297
|
-
"InstanceId": {"Ref": "Frontend"}
|
435
|
+
"SecurityGroupEgress": [
|
436
|
+
{"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0"}
|
437
|
+
]
|
298
438
|
}},
|
299
439
|
|
300
|
-
"
|
301
|
-
"Instances": [{"Ref": "
|
440
|
+
"ClientAPILoadBalancer": {"Type": "AWS::ElasticLoadBalancing::LoadBalancer", "Properties": {
|
441
|
+
"Instances": [{"Ref": "FrontendInstance"}],
|
302
442
|
"Subnets": [{"Ref": "PublicSubnet"}],
|
303
|
-
"SecurityGroups": [{"Ref": "
|
443
|
+
"SecurityGroups": [{"Ref": "ClientAPISecurityGroup"}],
|
304
444
|
|
305
445
|
"HealthCheck": {
|
306
|
-
"HealthyThreshold": "
|
307
|
-
"Interval": "
|
446
|
+
"HealthyThreshold": "3",
|
447
|
+
"Interval": "15",
|
308
448
|
"Target": "HTTP:80/v1/info",
|
309
449
|
"Timeout": "5",
|
310
|
-
"UnhealthyThreshold": "
|
450
|
+
"UnhealthyThreshold": "3"
|
311
451
|
},
|
312
452
|
|
313
453
|
"Listeners": [{
|
@@ -317,107 +457,43 @@
|
|
317
457
|
"InstanceProtocol": "TCP",
|
318
458
|
|
319
459
|
"SSLCertificateId": {"Fn::Join": ["", [
|
320
|
-
"arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":server-certificate/",
|
321
|
-
<%= j
|
460
|
+
"arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":server-certificate/cloudfront/",
|
461
|
+
<%= j @stack.name %>, "/", <%= j frontend_cert_path %>
|
322
462
|
]]}
|
323
463
|
}]
|
324
464
|
}},
|
325
465
|
|
326
|
-
"
|
466
|
+
"ClientAPIDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
327
467
|
"HostedZoneId": <%= j hosted_zone %>,
|
328
468
|
"Type": "CNAME", "TTL": "300",
|
329
469
|
"Name": <%= j "api.#{domain}." %>,
|
330
|
-
"ResourceRecords": [{"Fn::GetAtt": ["
|
470
|
+
"ResourceRecords": [{"Fn::GetAtt": ["ClientAPILoadBalancer", "DNSName"]}]
|
331
471
|
}},
|
332
472
|
|
333
|
-
"
|
334
|
-
"GroupDescription": "
|
473
|
+
"AdminAPISecurityGroup": {"Type": "AWS::EC2::SecurityGroup", "Properties": {
|
474
|
+
"GroupDescription": "Admin API security group",
|
335
475
|
"VpcId": {"Ref": "VPC"},
|
336
476
|
|
337
477
|
"SecurityGroupIngress": [
|
338
|
-
{"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "CidrIp": "
|
478
|
+
{"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "CidrIp": "10.0.0.0/16"}
|
339
479
|
],
|
340
480
|
"SecurityGroupEgress": [
|
341
481
|
{"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0"}
|
342
482
|
]
|
343
483
|
}},
|
344
484
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
"Backend": {"Type": "AWS::EC2::Instance", "Properties": {
|
349
|
-
"InstanceType": "m3.medium",
|
350
|
-
"ImageId": <%= j ubuntu_daily_ami %>,
|
351
|
-
|
352
|
-
"Tags": [
|
353
|
-
{ "Key": "Name", "Value": "app01" },
|
354
|
-
{ "Key": "Environment", "Value": <%= j environment %> }
|
355
|
-
],
|
356
|
-
|
357
|
-
"KeyName": <%= j @stack.iam_keypair_name %>,
|
358
|
-
|
359
|
-
"BlockDeviceMappings": [
|
360
|
-
{"DeviceName": "/dev/xvdc", "Ebs": {
|
361
|
-
"SnapshotId": <%= j docker_library_snapshot %>,
|
362
|
-
"VolumeSize": "50"
|
363
|
-
}},
|
364
|
-
|
365
|
-
{"DeviceName": "/dev/xvdd", "Ebs": {
|
366
|
-
"VolumeSize": "300"
|
367
|
-
}}
|
368
|
-
],
|
369
|
-
|
370
|
-
"NetworkInterfaces": [{
|
371
|
-
"Description": "Primary network interface",
|
372
|
-
"DeviceIndex": 0,
|
373
|
-
"DeleteOnTermination": true,
|
374
|
-
|
375
|
-
"SubnetId": {"Ref": "PrivateSubnet"},
|
376
|
-
"GroupSet": [{"Ref": "BackendSecurityGroup"}]
|
377
|
-
}],
|
378
|
-
|
379
|
-
"UserData": {"Fn::Base64": {"Fn::Join": ["", [
|
380
|
-
"#!/bin/bash -e\n",
|
381
|
-
"export AWS_WAIT_HANDLE='", {"Ref": "InstanceBootstrapWaitHandle"}, "'\n",
|
382
|
-
<%= ja 8, userdata['backend'] %>
|
383
|
-
]]}}
|
384
|
-
}},
|
385
|
-
|
386
|
-
"BackendSecurityGroup": {"Type": "AWS::EC2::SecurityGroup", "Properties": {
|
387
|
-
"GroupDescription": "Enable SSH access via port 22",
|
388
|
-
"VpcId": {"Ref": "VPC"},
|
389
|
-
|
390
|
-
"SecurityGroupIngress": [
|
391
|
-
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": <%= j external_ssh_cidr %>},
|
392
|
-
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": <%= j bastion_ssh_cidr %>},
|
393
|
-
{"IpProtocol": "tcp", "FromPort": "51607", "ToPort": "51607", "CidrIp": "10.100.0.0/24"}
|
394
|
-
],
|
395
|
-
"SecurityGroupEgress": [
|
396
|
-
{"IpProtocol": "-1", "CidrIp": "0.0.0.0/0"}
|
397
|
-
]
|
398
|
-
}
|
399
|
-
},
|
400
|
-
|
401
|
-
"BackendEIP": {"Type": "AWS::EC2::EIP", "Properties": {
|
402
|
-
"Domain": "VPC"
|
403
|
-
}},
|
404
|
-
"BackendEIPAssociation": {"Type": "AWS::EC2::EIPAssociation", "Properties": {
|
405
|
-
"AllocationId": {"Fn::GetAtt": ["BackendEIP", "AllocationId"]},
|
406
|
-
"InstanceId": {"Ref": "Backend"}
|
407
|
-
}},
|
408
|
-
|
409
|
-
"BackendEndpoint": {"Type": "AWS::ElasticLoadBalancing::LoadBalancer", "Properties": {
|
410
|
-
"Instances": [{"Ref": "Backend"}],
|
411
|
-
"Subnets": [{"Ref": "PrivateSubnet"}],
|
412
|
-
"SecurityGroups": [{"Ref": "BackendEndpointSecurityGroup"}],
|
485
|
+
"AdminAPILoadBalancer": {"Type": "AWS::ElasticLoadBalancing::LoadBalancer", "Properties": {
|
486
|
+
"Instances": [{"Ref": "BackendInstance"}],
|
487
|
+
"Subnets": [{"Ref": "PublicSubnet"}],
|
413
488
|
"Scheme": "internal",
|
489
|
+
"SecurityGroups": [{"Ref": "AdminAPISecurityGroup"}],
|
414
490
|
|
415
491
|
"HealthCheck": {
|
416
|
-
"HealthyThreshold": "
|
417
|
-
"Interval": "
|
492
|
+
"HealthyThreshold": "3",
|
493
|
+
"Interval": "15",
|
418
494
|
"Target": "HTTP:80/v1/info",
|
419
495
|
"Timeout": "5",
|
420
|
-
"UnhealthyThreshold": "
|
496
|
+
"UnhealthyThreshold": "3"
|
421
497
|
},
|
422
498
|
|
423
499
|
"Listeners": [{
|
@@ -427,111 +503,269 @@
|
|
427
503
|
"InstanceProtocol": "TCP",
|
428
504
|
|
429
505
|
"SSLCertificateId": {"Fn::Join": ["", [
|
430
|
-
"arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":server-certificate/",
|
431
|
-
<%= j
|
506
|
+
"arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":server-certificate/cloudfront/",
|
507
|
+
<%= j @stack.name %>, "/", <%= j backend_cert_path %>
|
432
508
|
]]}
|
433
509
|
}]
|
434
510
|
}},
|
435
511
|
|
436
|
-
"
|
512
|
+
"AdminAPIDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
437
513
|
"HostedZoneId": <%= j hosted_zone %>,
|
438
514
|
"Type": "CNAME", "TTL": "300",
|
439
515
|
"Name": <%= j "api.admin.#{domain}." %>,
|
440
|
-
"ResourceRecords": [{"Fn::GetAtt": ["
|
516
|
+
"ResourceRecords": [{"Fn::GetAtt": ["AdminAPILoadBalancer", "DNSName"]}]
|
441
517
|
}},
|
518
|
+
<% end %>
|
442
519
|
|
443
|
-
"BackendEndpointSecurityGroup": {"Type": "AWS::EC2::SecurityGroup", "Properties": {
|
444
|
-
"GroupDescription": "Backend ELB security group",
|
445
|
-
"VpcId": {"Ref": "VPC"},
|
446
520
|
|
447
|
-
"SecurityGroupIngress": [
|
448
|
-
{"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "CidrIp": "10.100.0.0/24"}
|
449
|
-
],
|
450
|
-
"SecurityGroupEgress": [
|
451
|
-
{"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0"}
|
452
|
-
]
|
453
|
-
}},
|
454
521
|
|
455
|
-
"BackendIngress": {"Type": "AWS::EC2::SecurityGroupIngress", "Properties": {
|
456
|
-
"GroupId": {"Ref": "BackendSecurityGroup"},
|
457
|
-
"SourceSecurityGroupId": {"Ref": "BackendEndpointSecurityGroup"},
|
458
522
|
|
459
|
-
"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80"
|
460
|
-
}},
|
461
523
|
|
462
524
|
|
463
525
|
|
464
526
|
|
465
527
|
|
466
528
|
|
467
|
-
|
468
|
-
|
469
|
-
"
|
470
|
-
"
|
529
|
+
<% if layers_enabled.member? :static %>
|
530
|
+
"ClientAppBucket": {"Type": "AWS::S3::Bucket", "Properties": {
|
531
|
+
"BucketName": <%= j domain %>,
|
532
|
+
"AccessControl": "PublicRead",
|
533
|
+
"WebsiteConfiguration": {
|
534
|
+
"IndexDocument": "index.html",
|
535
|
+
"ErrorDocument": "404.html"
|
536
|
+
}
|
537
|
+
}},
|
471
538
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
539
|
+
"ClientAppDistribution": {"Type": "AWS::CloudFront::Distribution", "Properties": {
|
540
|
+
"DistributionConfig": {
|
541
|
+
"Aliases": [<%= j domain %>],
|
542
|
+
"Enabled": "true",
|
476
543
|
|
477
|
-
|
544
|
+
"Origins": [{
|
545
|
+
"Id": "ClientAppBucketOrigin",
|
546
|
+
"DomainName": {"Fn::Join": ["", [<%= j domain %>, ".s3-website-", {"Ref": "AWS::Region"}, ".amazonaws.com"]]},
|
478
547
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
"Description": "Private network interface",
|
486
|
-
"DeviceIndex": "1",
|
487
|
-
"DeleteOnTermination": true,
|
548
|
+
"CustomOriginConfig": {
|
549
|
+
"HTTPPort": "80",
|
550
|
+
"HTTPSPort": "443",
|
551
|
+
"OriginProtocolPolicy": "http-only"
|
552
|
+
}
|
553
|
+
}],
|
488
554
|
|
489
|
-
|
490
|
-
"
|
555
|
+
"DefaultCacheBehavior": {
|
556
|
+
"TargetOriginId": "ClientAppBucketOrigin",
|
557
|
+
"ForwardedValues": {"QueryString": "false"},
|
558
|
+
"ViewerProtocolPolicy": "redirect-to-https"
|
491
559
|
}
|
492
|
-
|
560
|
+
}
|
561
|
+
}},
|
493
562
|
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
563
|
+
"ClientAppDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
564
|
+
"HostedZoneId": <%= j hosted_zone %>,
|
565
|
+
"Type": "A",
|
566
|
+
"Name": <%= j "#{domain}." %>,
|
567
|
+
"AliasTarget": {
|
568
|
+
"HostedZoneId": <%= j @config['cloudfront']['hosted_zone'] %>,
|
569
|
+
"DNSName": {"Fn::GetAtt": ["ClientAppDistribution", "DomainName"]}
|
570
|
+
}
|
571
|
+
}},
|
572
|
+
|
573
|
+
|
574
|
+
|
575
|
+
"AdminAppBucket": {"Type": "AWS::S3::Bucket", "Properties": {
|
576
|
+
"BucketName": <%= j "admin.#{domain}" %>,
|
577
|
+
"AccessControl": "PublicRead",
|
578
|
+
"WebsiteConfiguration": {
|
579
|
+
"IndexDocument": "index.html",
|
580
|
+
"ErrorDocument": "404.html"
|
581
|
+
}
|
499
582
|
}},
|
500
583
|
|
501
|
-
"
|
502
|
-
"
|
584
|
+
"AdminAppDistribution": {"Type": "AWS::CloudFront::Distribution", "Properties": {
|
585
|
+
"DistributionConfig": {
|
586
|
+
"Aliases": [<%= j "admin.#{domain}" %>],
|
587
|
+
"Enabled": "true",
|
588
|
+
|
589
|
+
"Origins": [{
|
590
|
+
"Id": "AdminAppBucketOrigin",
|
591
|
+
"DomainName": {"Fn::Join": ["", [<%= j "admin.#{domain}" %>, ".s3-website-", {"Ref": "AWS::Region"}, ".amazonaws.com"]]},
|
592
|
+
|
593
|
+
"CustomOriginConfig": {
|
594
|
+
"HTTPPort": "80",
|
595
|
+
"HTTPSPort": "443",
|
596
|
+
"OriginProtocolPolicy": "http-only"
|
597
|
+
}
|
598
|
+
}],
|
503
599
|
|
504
|
-
|
505
|
-
|
600
|
+
"DefaultCacheBehavior": {
|
601
|
+
"TargetOriginId": "AdminAppBucketOrigin",
|
602
|
+
"ForwardedValues": {"QueryString": "false"},
|
603
|
+
"ViewerProtocolPolicy": "redirect-to-https"
|
604
|
+
}
|
605
|
+
}
|
506
606
|
}},
|
507
607
|
|
508
|
-
"
|
509
|
-
"
|
608
|
+
"AdminAppDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
609
|
+
"HostedZoneId": <%= j hosted_zone %>,
|
610
|
+
"Type": "CNAME", "TTL": "300",
|
611
|
+
"Name": <%= j "admin.#{domain}." %>,
|
612
|
+
"ResourceRecords": [{"Fn::GetAtt": ["AdminAppDistribution", "DomainName"]}]
|
510
613
|
}},
|
511
614
|
|
512
|
-
|
513
|
-
|
514
|
-
|
615
|
+
|
616
|
+
|
617
|
+
"WwwRedirectorBucket": {"Type": "AWS::S3::Bucket", "Properties": {
|
618
|
+
"BucketName": <%= j "www.#{domain}" %>,
|
619
|
+
"AccessControl": "PublicRead",
|
620
|
+
"WebsiteConfiguration": {
|
621
|
+
"RedirectAllRequestsTo": {
|
622
|
+
"HostName": <%= j domain %>,
|
623
|
+
"Protocol": "https"
|
624
|
+
}
|
625
|
+
}
|
626
|
+
}},
|
627
|
+
|
628
|
+
"WwwRedirectorDistribution": {"Type": "AWS::CloudFront::Distribution", "Properties": {
|
629
|
+
"DistributionConfig": {
|
630
|
+
"Aliases": [<%= j "www.#{domain}" %>],
|
631
|
+
"Enabled": "true",
|
632
|
+
|
633
|
+
"Origins": [{
|
634
|
+
"Id": "WwwRedirectorBucketOrigin",
|
635
|
+
"DomainName": {"Fn::Join": ["", [<%= j "www.#{domain}" %>, ".s3-website-", {"Ref": "AWS::Region"}, ".amazonaws.com"]]},
|
636
|
+
|
637
|
+
"CustomOriginConfig": {
|
638
|
+
"HTTPPort": "80",
|
639
|
+
"HTTPSPort": "443",
|
640
|
+
"OriginProtocolPolicy": "http-only"
|
641
|
+
}
|
642
|
+
}],
|
643
|
+
|
644
|
+
"DefaultCacheBehavior": {
|
645
|
+
"TargetOriginId": "WwwRedirectorBucketOrigin",
|
646
|
+
"ForwardedValues": {"QueryString": "false"},
|
647
|
+
"ViewerProtocolPolicy": "redirect-to-https"
|
648
|
+
}
|
649
|
+
}
|
515
650
|
}},
|
516
651
|
|
517
|
-
"
|
652
|
+
"WwwRedirectorDNSRecord": {"Type": "AWS::Route53::RecordSet", "Properties": {
|
518
653
|
"HostedZoneId": <%= j hosted_zone %>,
|
519
654
|
"Type": "CNAME", "TTL": "300",
|
520
|
-
"Name": <%= j "
|
521
|
-
"ResourceRecords": [{"Fn::GetAtt": ["
|
655
|
+
"Name": <%= j "www.#{domain}." %>,
|
656
|
+
"ResourceRecords": [{"Fn::GetAtt": ["WwwRedirectorDistribution", "DomainName"]}]
|
522
657
|
}},
|
658
|
+
<% end %>
|
659
|
+
|
660
|
+
|
661
|
+
|
662
|
+
|
663
|
+
<% if layers_enabled.member? :instances %>
|
664
|
+
"BackendSecurityGroup" : {
|
665
|
+
"Type" : "AWS::EC2::SecurityGroup",
|
666
|
+
"Properties" : {
|
667
|
+
"GroupDescription" : "Allow the application instances to access the NAT device",
|
668
|
+
"VpcId" : { "Ref" : "VPC" },
|
669
|
+
"SecurityGroupIngress": [
|
670
|
+
{ "IpProtocol": "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupId" : { "Ref" : "AdminAPISecurityGroup" }},
|
671
|
+
{"IpProtocol": "tcp", "FromPort": "51607", "ToPort": "51607", "SourceSecurityGroupId": { "Ref" : "FrontendSecurityGroup" }},
|
672
|
+
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0"}
|
673
|
+
],
|
674
|
+
"SecurityGroupEgress": [
|
675
|
+
{"IpProtocol": "-1", "CidrIp": "0.0.0.0/0"}
|
676
|
+
]
|
677
|
+
}
|
678
|
+
},
|
679
|
+
|
680
|
+
"BackendInstanceConfigurationWaitHandle": {"Type": "AWS::CloudFormation::WaitConditionHandle", "Properties": {}},
|
681
|
+
|
682
|
+
"BackendInstanceConfiguration": {"Type": "AWS::CloudFormation::WaitCondition", "DependsOn": ["BackendInstance"], "Properties": {
|
683
|
+
"Handle": {"Ref": "BackendInstanceConfigurationWaitHandle"},
|
684
|
+
"Count": "1",
|
685
|
+
"Timeout": "1200"
|
686
|
+
}},
|
687
|
+
|
688
|
+
"BackendInstance" : {
|
689
|
+
"Type" : "AWS::EC2::Instance",
|
690
|
+
"DependsOn": "NATDeviceConfiguration",
|
691
|
+
"Properties" : {
|
692
|
+
"InstanceType": "m3.medium",
|
693
|
+
"ImageId": <%= j ubuntu_daily_ami %>,
|
694
|
+
"SubnetId" : { "Ref" : "PrivateSubnet" },
|
695
|
+
"SecurityGroupIds" : [{ "Ref" : "BackendSecurityGroup" }],
|
696
|
+
"KeyName": <%= j @stack.iam_keypair_name %>,
|
697
|
+
"BlockDeviceMappings": [
|
698
|
+
{"DeviceName": "/dev/xvdc", "Ebs": {
|
699
|
+
"SnapshotId": <%= j docker_library_snapshot %>,
|
700
|
+
"VolumeSize": "50"
|
701
|
+
}},
|
702
|
+
|
703
|
+
{"DeviceName": "/dev/xvdd", "Ebs": {
|
704
|
+
"VolumeSize": "300"
|
705
|
+
}}
|
706
|
+
],
|
707
|
+
|
708
|
+
"UserData": {"Fn::Base64": {"Fn::Join": ["", [
|
709
|
+
"#!/bin/bash -e\n",
|
710
|
+
"export AWS_WAIT_HANDLE='", {"Ref": "BackendInstanceConfigurationWaitHandle"}, "'\n",
|
711
|
+
<%= ja 8, userdata['backend'] %>
|
712
|
+
]]}}
|
713
|
+
}
|
714
|
+
},
|
715
|
+
|
716
|
+
|
717
|
+
|
718
|
+
"FrontendSecurityGroup" : {
|
719
|
+
"Type" : "AWS::EC2::SecurityGroup",
|
720
|
+
"Properties" : {
|
721
|
+
"GroupDescription" : "Allow the application instances to access the NAT device",
|
722
|
+
"VpcId" : { "Ref" : "VPC" },
|
723
|
+
"SecurityGroupIngress": [
|
724
|
+
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp": "0.0.0.0/0"},
|
725
|
+
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0"}
|
726
|
+
],
|
727
|
+
"SecurityGroupEgress": [
|
728
|
+
{"IpProtocol": "-1", "CidrIp": "0.0.0.0/0"}
|
729
|
+
]
|
730
|
+
}
|
731
|
+
},
|
732
|
+
|
733
|
+
"FrontendInstance" : {
|
734
|
+
"Type" : "AWS::EC2::Instance",
|
735
|
+
"DependsOn": "BackendInstanceConfiguration",
|
736
|
+
"Properties" : {
|
737
|
+
"InstanceType": "m1.small",
|
738
|
+
"ImageId": <%= j ubuntu_daily_ami %>,
|
739
|
+
"SubnetId" : { "Ref" : "PrivateSubnet" },
|
740
|
+
"SecurityGroupIds" : [{ "Ref" : "FrontendSecurityGroup" }],
|
741
|
+
"KeyName": <%= j @stack.iam_keypair_name %>,
|
742
|
+
"BlockDeviceMappings": [
|
743
|
+
{"DeviceName": "/dev/xvdc", "Ebs": {
|
744
|
+
"SnapshotId": <%= j docker_library_snapshot %>,
|
745
|
+
"VolumeSize": "50"
|
746
|
+
}},
|
747
|
+
|
748
|
+
{"DeviceName": "/dev/xvdd", "Ebs": {
|
749
|
+
"VolumeSize": "300"
|
750
|
+
}}
|
751
|
+
],
|
752
|
+
|
753
|
+
"UserData": {"Fn::Base64": {"Fn::Join": ["", [
|
754
|
+
"#!/bin/bash -e\n",
|
755
|
+
"export BACKEND_HOST='", {"Fn::GetAtt": ["BackendInstance", "PrivateDnsName"]}, "'\n",
|
756
|
+
<%= ja 8, userdata['frontend'] %>
|
757
|
+
]]}}
|
758
|
+
}
|
759
|
+
}
|
760
|
+
<% end %>
|
761
|
+
|
762
|
+
|
763
|
+
|
764
|
+
|
765
|
+
|
766
|
+
|
523
767
|
|
524
|
-
"OpenVPNSecurityGroup": {"Type": "AWS::EC2::SecurityGroup", "Properties": {
|
525
|
-
"GroupDescription": "Enable everything",
|
526
|
-
"VpcId": {"Ref": "VPC"},
|
527
768
|
|
528
|
-
"SecurityGroupIngress": [
|
529
|
-
{"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "CidrIp": "0.0.0.0/0"},
|
530
|
-
{"IpProtocol": "udp", "FromPort": "1192", "ToPort": "1194", "CidrIp": "0.0.0.0/0"},
|
531
|
-
{"IpProtocol": "tcp", "FromPort": "943", "ToPort": "943", "CidrIp": "0.0.0.0/0"},
|
532
|
-
{"IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0"}
|
533
|
-
]
|
534
|
-
}}
|
535
769
|
|
536
770
|
}
|
537
771
|
}
|