terrafying-components 1.4.3 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/hash/merge_with_arrays.rb +7 -0
- data/lib/terrafying/components.rb +10 -0
- data/lib/terrafying/components/auditd.rb +158 -0
- data/lib/terrafying/components/ca.rb +55 -0
- data/lib/terrafying/components/dynamicset.rb +229 -0
- data/lib/terrafying/components/endpoint.rb +96 -0
- data/lib/terrafying/components/endpointservice.rb +63 -0
- data/lib/terrafying/components/ignition.rb +117 -0
- data/lib/terrafying/components/instance.rb +112 -0
- data/lib/terrafying/components/instanceprofile.rb +81 -0
- data/lib/terrafying/components/letsencrypt.rb +146 -0
- data/lib/terrafying/components/loadbalancer.rb +159 -0
- data/lib/terrafying/components/ports.rb +35 -0
- data/lib/terrafying/components/selfsignedca.rb +171 -0
- data/lib/terrafying/components/service.rb +148 -0
- data/lib/terrafying/components/staticset.rb +153 -0
- data/lib/terrafying/components/subnet.rb +105 -0
- data/lib/terrafying/components/support/deregister-vpn +48 -0
- data/lib/terrafying/components/support/register-vpn +46 -0
- data/lib/terrafying/components/templates/ignition.yaml +115 -0
- data/lib/terrafying/components/usable.rb +129 -0
- data/lib/terrafying/components/version.rb +5 -0
- data/lib/terrafying/components/vpc.rb +417 -0
- data/lib/terrafying/components/vpn.rb +358 -0
- data/lib/terrafying/components/zone.rb +144 -0
- metadata +28 -31
@@ -0,0 +1,148 @@
|
|
1
|
+
|
2
|
+
require 'digest'
|
3
|
+
require 'hash/merge_with_arrays'
|
4
|
+
require 'terrafying/generator'
|
5
|
+
require 'terrafying/util'
|
6
|
+
require 'terrafying/components/auditd'
|
7
|
+
require 'terrafying/components/dynamicset'
|
8
|
+
require 'terrafying/components/endpointservice'
|
9
|
+
require 'terrafying/components/ignition'
|
10
|
+
require 'terrafying/components/instance'
|
11
|
+
require 'terrafying/components/instanceprofile'
|
12
|
+
require 'terrafying/components/loadbalancer'
|
13
|
+
require 'terrafying/components/selfsignedca'
|
14
|
+
require 'terrafying/components/staticset'
|
15
|
+
require 'terrafying/components/usable'
|
16
|
+
|
17
|
+
module Terrafying
|
18
|
+
|
19
|
+
module Components
|
20
|
+
|
21
|
+
class Service < Terrafying::Context
|
22
|
+
|
23
|
+
attr_reader :name, :domain_names, :ports, :load_balancer, :instance_set
|
24
|
+
|
25
|
+
include Usable
|
26
|
+
|
27
|
+
def self.create_in(vpc, name, options={})
|
28
|
+
Service.new.create_in vpc, name, options
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.find_in(vpc, name)
|
32
|
+
Service.new.find_in vpc, name
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize()
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_in(vpc, name)
|
40
|
+
raise 'unimplemented'
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_in(vpc, name, options={})
|
44
|
+
options = {
|
45
|
+
ami: aws.ami("base-image-59a5b709", owners=["136393635417"]),
|
46
|
+
instance_type: "t2.micro",
|
47
|
+
ports: [],
|
48
|
+
instances: [{}],
|
49
|
+
zone: vpc.zone,
|
50
|
+
iam_policy_statements: [],
|
51
|
+
security_groups: [],
|
52
|
+
keypairs: [],
|
53
|
+
volumes: [],
|
54
|
+
units: [],
|
55
|
+
files: [],
|
56
|
+
tags: {},
|
57
|
+
ssh_group: vpc.ssh_group,
|
58
|
+
subnets: vpc.subnets.fetch(:private, []),
|
59
|
+
startup_grace_period: 300,
|
60
|
+
depends_on: [],
|
61
|
+
audit_role: "arn:aws:iam::#{aws.account_id}:role/auditd_logging"
|
62
|
+
}.merge(options)
|
63
|
+
|
64
|
+
unless options[:audit_role].nil?
|
65
|
+
fluentd_conf = Auditd.fluentd_conf(options[:audit_role], options[:tags].keys)
|
66
|
+
options = options.merge_with_arrays_merged(fluentd_conf)
|
67
|
+
end
|
68
|
+
|
69
|
+
if ! options.has_key? :user_data
|
70
|
+
options[:user_data] = Ignition.generate(options)
|
71
|
+
end
|
72
|
+
|
73
|
+
if ! options.has_key?(:loadbalancer_subnets)
|
74
|
+
options[:loadbalancer_subnets] = options[:subnets]
|
75
|
+
end
|
76
|
+
|
77
|
+
unless options[:instances].is_a?(Hash) or options[:instances].is_a?(Array)
|
78
|
+
raise 'Unknown instances option, should be hash or array'
|
79
|
+
end
|
80
|
+
|
81
|
+
ident = "#{tf_safe(vpc.name)}-#{name}"
|
82
|
+
|
83
|
+
@name = ident
|
84
|
+
@ports = enrich_ports(options[:ports])
|
85
|
+
@domain_names = [ options[:zone].qualify(name) ]
|
86
|
+
|
87
|
+
depends_on = options[:depends_on] + options[:keypairs].map{ |kp| kp[:resources] }.flatten
|
88
|
+
|
89
|
+
iam_statements = options[:iam_policy_statements] + options[:keypairs].map { |kp| kp[:iam_statement] }
|
90
|
+
instance_profile = add! InstanceProfile.create(ident, { statements: iam_statements })
|
91
|
+
|
92
|
+
tags = options[:tags].merge({ service_name: name })
|
93
|
+
|
94
|
+
set = options[:instances].is_a?(Hash) ? DynamicSet : StaticSet
|
95
|
+
|
96
|
+
wants_load_balancer = (set == DynamicSet && @ports.count > 0) || options[:loadbalancer]
|
97
|
+
|
98
|
+
instance_set_options = {
|
99
|
+
instance_profile: instance_profile,
|
100
|
+
depends_on: depends_on,
|
101
|
+
tags: tags,
|
102
|
+
}
|
103
|
+
|
104
|
+
if wants_load_balancer && @ports.any? { |p| p.has_key?(:health_check) }
|
105
|
+
instance_set_options[:health_check] = { type: "ELB", grace_period: options[:startup_grace_period] }
|
106
|
+
end
|
107
|
+
|
108
|
+
@instance_set = add! set.create_in(vpc, name, options.merge(instance_set_options))
|
109
|
+
@security_group = @instance_set.security_group
|
110
|
+
|
111
|
+
if wants_load_balancer
|
112
|
+
@load_balancer = add! LoadBalancer.create_in(
|
113
|
+
vpc, name, options.merge(
|
114
|
+
{
|
115
|
+
subnets: options[:loadbalancer_subnets],
|
116
|
+
tags: tags,
|
117
|
+
}
|
118
|
+
),
|
119
|
+
)
|
120
|
+
|
121
|
+
@load_balancer.attach(@instance_set)
|
122
|
+
|
123
|
+
if @load_balancer.type == "application"
|
124
|
+
@security_group = @load_balancer.security_group
|
125
|
+
@egress_security_group = @instance_set.security_group
|
126
|
+
end
|
127
|
+
|
128
|
+
vpc.zone.add_alias_in(self, name, @load_balancer.alias_config)
|
129
|
+
elsif set == StaticSet
|
130
|
+
vpc.zone.add_record_in(self, name, @instance_set.instances.map { |i| i.ip_address })
|
131
|
+
@instance_set.instances.each { |i|
|
132
|
+
@domain_names << vpc.zone.qualify(i.name)
|
133
|
+
vpc.zone.add_record_in(self, i.name, [i.ip_address])
|
134
|
+
}
|
135
|
+
end
|
136
|
+
\
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
140
|
+
def with_endpoint_service(options = {})
|
141
|
+
add! EndpointService.create_for(@load_balancer, @name, options)
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
|
2
|
+
require 'xxhash'
|
3
|
+
|
4
|
+
require 'terrafying/components/instance'
|
5
|
+
require 'terrafying/components/usable'
|
6
|
+
|
7
|
+
require_relative './ports'
|
8
|
+
|
9
|
+
module Terrafying
|
10
|
+
|
11
|
+
module Components
|
12
|
+
|
13
|
+
class StaticSet < Terrafying::Context
|
14
|
+
|
15
|
+
attr_reader :name, :instances
|
16
|
+
|
17
|
+
include Usable
|
18
|
+
|
19
|
+
def self.create_in(vpc, name, options={})
|
20
|
+
StaticSet.new.create_in vpc, name, options
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.find_in(vpc, name)
|
24
|
+
StaticSet.new.find_in vpc, name
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize()
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_in(vpc, name)
|
32
|
+
@name = name
|
33
|
+
|
34
|
+
raise 'unimplemented'
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_in(vpc, name, options={})
|
40
|
+
options = {
|
41
|
+
public: false,
|
42
|
+
ami: aws.ami("base-image-59a5b709", owners=["136393635417"]),
|
43
|
+
instance_type: "t2.micro",
|
44
|
+
subnets: vpc.subnets.fetch(:private, []),
|
45
|
+
ports: [],
|
46
|
+
instances: [{}],
|
47
|
+
instance_profile: nil,
|
48
|
+
security_groups: [],
|
49
|
+
user_data: "",
|
50
|
+
tags: {},
|
51
|
+
ssh_group: vpc.ssh_group,
|
52
|
+
depends_on: [],
|
53
|
+
volumes: [],
|
54
|
+
}.merge(options)
|
55
|
+
|
56
|
+
ident = "#{tf_safe(vpc.name)}-#{name}"
|
57
|
+
|
58
|
+
@name = ident
|
59
|
+
@ports = enrich_ports(options[:ports])
|
60
|
+
|
61
|
+
@security_group = resource :aws_security_group, ident, {
|
62
|
+
name: "staticset-#{ident}",
|
63
|
+
description: "Describe the ingress and egress of the static set #{ident}",
|
64
|
+
tags: options[:tags],
|
65
|
+
vpc_id: vpc.id,
|
66
|
+
egress: [
|
67
|
+
{
|
68
|
+
from_port: 0,
|
69
|
+
to_port: 0,
|
70
|
+
protocol: -1,
|
71
|
+
cidr_blocks: ["0.0.0.0/0"],
|
72
|
+
}
|
73
|
+
],
|
74
|
+
}
|
75
|
+
|
76
|
+
path_mtu_setup!
|
77
|
+
|
78
|
+
@instances = options[:instances].map.with_index do |config, i|
|
79
|
+
instance_ident = "#{name}-#{i}"
|
80
|
+
|
81
|
+
instance = add! Instance.create_in(
|
82
|
+
vpc, instance_ident, options.merge(
|
83
|
+
{
|
84
|
+
subnets: options[:subnets],
|
85
|
+
security_groups: [@security_group] + options[:security_groups],
|
86
|
+
depends_on: options[:depends_on],
|
87
|
+
instance_profile: options[:instance_profile],
|
88
|
+
tags: {
|
89
|
+
staticset_name: ident,
|
90
|
+
}.merge(options[:tags])
|
91
|
+
}.merge(config)
|
92
|
+
)
|
93
|
+
)
|
94
|
+
|
95
|
+
options[:volumes].each.with_index { |volume, vol_i|
|
96
|
+
volume_for("#{instance_ident}-#{vol_i}", instance, volume, options[:tags])
|
97
|
+
}
|
98
|
+
|
99
|
+
instance
|
100
|
+
end
|
101
|
+
|
102
|
+
@ports.each { |port|
|
103
|
+
resource :aws_security_group_rule, "#{@name}-to-self-#{port[:name]}", {
|
104
|
+
security_group_id: @security_group,
|
105
|
+
type: "ingress",
|
106
|
+
from_port: port[:upstream_port],
|
107
|
+
to_port: port[:upstream_port],
|
108
|
+
protocol: port[:type],
|
109
|
+
self: true,
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
def volume_for(name, instance, volume, tags)
|
117
|
+
vol_opts = {
|
118
|
+
availability_zone: instance.subnet.az,
|
119
|
+
size: volume[:size],
|
120
|
+
type: volume[:type] || 'gp2',
|
121
|
+
encrypted: volume[:encrypted] || false,
|
122
|
+
kms_key_id: volume[:kms_key_id],
|
123
|
+
tags: {
|
124
|
+
Name: name
|
125
|
+
}.merge(tags)
|
126
|
+
}.reject { |_, v| v.nil? }
|
127
|
+
|
128
|
+
volume_id = resource :aws_ebs_volume, name, vol_opts
|
129
|
+
|
130
|
+
resource :aws_volume_attachment, name, {
|
131
|
+
device_name: volume[:device],
|
132
|
+
volume_id: volume_id,
|
133
|
+
instance_id: instance.id,
|
134
|
+
force_detach: true
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
def attach_load_balancer(load_balancer)
|
139
|
+
@instances.product(load_balancer.target_groups).each.with_index { |(instance, target_group), i|
|
140
|
+
resource :aws_lb_target_group_attachment, "#{load_balancer.name}-#{@name}-#{i}", {
|
141
|
+
target_group_arn: target_group,
|
142
|
+
target_id: instance.id,
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
self.used_by(load_balancer) if load_balancer.type == "application"
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
require 'netaddr'
|
3
|
+
|
4
|
+
require 'terrafying/generator'
|
5
|
+
|
6
|
+
module Terrafying
|
7
|
+
|
8
|
+
module Components
|
9
|
+
|
10
|
+
CIDR_PADDING = 5
|
11
|
+
|
12
|
+
class Subnet < Terrafying::Context
|
13
|
+
|
14
|
+
attr_reader :id, :cidr, :az, :public, :route_table
|
15
|
+
|
16
|
+
def self.create_in(vpc, name, az, cidr, options={})
|
17
|
+
Subnet.new.create_in vpc, name, az, cidr, options
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find(id)
|
21
|
+
Subnet.new.find(id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize()
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def find(id)
|
29
|
+
subnet = aws.subnet_by_id(id)
|
30
|
+
|
31
|
+
@id = id
|
32
|
+
@cidr = subnet.cidr_block
|
33
|
+
@az = subnet.availability_zone
|
34
|
+
|
35
|
+
begin
|
36
|
+
route_table = aws.route_table_for_subnet(id)
|
37
|
+
rescue
|
38
|
+
# fallback to main route table if ones not explicitly associated
|
39
|
+
route_table = aws.route_table_for_vpc(subnet.vpc_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
@route_table = route_table.route_table_id
|
43
|
+
@public = route_table.routes.select { |r| r.destination_cidr_block == "0.0.0.0/0" }.first.gateway_id != nil
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_in(vpc, name, az, cidr, options={})
|
49
|
+
options = {
|
50
|
+
tags: {},
|
51
|
+
}.merge(options)
|
52
|
+
|
53
|
+
ident = "#{tf_safe(vpc.name)}-#{name}-#{az}"
|
54
|
+
|
55
|
+
@cidr = cidr
|
56
|
+
@az = az
|
57
|
+
@id = resource :aws_subnet, ident, {
|
58
|
+
vpc_id: vpc.id,
|
59
|
+
cidr_block: cidr,
|
60
|
+
availability_zone: az,
|
61
|
+
tags: { Name: ident }.merge(options[:tags]),
|
62
|
+
}
|
63
|
+
|
64
|
+
@route_table = resource :aws_route_table, ident, {
|
65
|
+
vpc_id: vpc.id,
|
66
|
+
tags: { Name: ident }.merge(options[:tags]),
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
if options[:nat_gateway]
|
72
|
+
gateway = { nat_gateway_id: options[:nat_gateway] }
|
73
|
+
@public = false
|
74
|
+
elsif options[:gateway]
|
75
|
+
gateway = { gateway_id: options[:gateway] }
|
76
|
+
@public = true
|
77
|
+
else
|
78
|
+
gateway = nil
|
79
|
+
@public = false
|
80
|
+
end
|
81
|
+
|
82
|
+
if gateway
|
83
|
+
resource :aws_route, "#{ident}-default", {
|
84
|
+
route_table_id: @route_table,
|
85
|
+
destination_cidr_block: "0.0.0.0/0",
|
86
|
+
}.merge(gateway)
|
87
|
+
end
|
88
|
+
|
89
|
+
resource :aws_route_table_association, ident, {
|
90
|
+
subnet_id: @id,
|
91
|
+
route_table_id: @route_table,
|
92
|
+
}
|
93
|
+
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
def ip_addresses
|
98
|
+
NetAddr::CIDR.create(@cidr).enumerate.drop(CIDR_PADDING)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -euo pipefail
|
4
|
+
|
5
|
+
app_id="${1}"
|
6
|
+
tenant_id="${2}"
|
7
|
+
new_fqdn="${3}"
|
8
|
+
|
9
|
+
set +u
|
10
|
+
if [[ ! -z $AZURE_USER ]] && [[ ! -z $AZURE_PASSWORD ]]
|
11
|
+
then
|
12
|
+
set -u
|
13
|
+
az login --service-principal \
|
14
|
+
--allow-no-subscriptions \
|
15
|
+
-t "${tenant_id}" \
|
16
|
+
-u "${AZURE_USER}" \
|
17
|
+
-p "${AZURE_PASSWORD}" >/dev/null
|
18
|
+
|
19
|
+
function finish {
|
20
|
+
exit_code=$?
|
21
|
+
az logout
|
22
|
+
exit $exit_code
|
23
|
+
}
|
24
|
+
trap finish EXIT
|
25
|
+
else
|
26
|
+
set -u
|
27
|
+
fi
|
28
|
+
|
29
|
+
app="$(az ad app show --id ${app_id})"
|
30
|
+
|
31
|
+
function urls() {
|
32
|
+
echo ${app} | jq -r '.replyUrls | join("\n")'
|
33
|
+
}
|
34
|
+
|
35
|
+
if [[ $? == 0 ]]
|
36
|
+
then
|
37
|
+
if urls | grep "${new_fqdn}" &>/dev/null
|
38
|
+
then
|
39
|
+
new_reply_urls="$(urls | grep -v "${new_fqdn}" | tr '\n' ' ')"
|
40
|
+
|
41
|
+
az ad app update --id ${app_id} --reply-urls ${new_reply_urls}
|
42
|
+
else
|
43
|
+
echo "Already doesn't contain a reply url for '${new_fqdn}'"
|
44
|
+
fi
|
45
|
+
else
|
46
|
+
echo "App wasn't found"
|
47
|
+
exit 1
|
48
|
+
fi
|