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.
@@ -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