cloud-mu 3.1.2 → 3.2.0
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/Dockerfile +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +10 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +920 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
|
@@ -203,6 +203,9 @@ module MU
|
|
|
203
203
|
# @param region [String]: The cloud provider region
|
|
204
204
|
# @return [void]
|
|
205
205
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
206
|
+
MU.log "AWS::Log.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
207
|
+
MU.log "Placeholder: AWS Log artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
|
|
208
|
+
|
|
206
209
|
log_groups = self.find(credentials: credentials, region: region).values
|
|
207
210
|
if !log_groups.empty?
|
|
208
211
|
log_groups.each{ |lg|
|
|
@@ -227,13 +230,13 @@ module MU
|
|
|
227
230
|
}
|
|
228
231
|
end
|
|
229
232
|
|
|
230
|
-
unless noop
|
|
231
|
-
MU::Cloud::AWS.iam(credentials: credentials).list_roles.roles.each{ |role|
|
|
232
|
-
match_string = "#{MU.deploy_id}.*CloudTrail"
|
|
233
|
-
# Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud
|
|
234
|
-
# MU::Cloud
|
|
235
|
-
}
|
|
236
|
-
end
|
|
233
|
+
# unless noop
|
|
234
|
+
# MU::Cloud::AWS.iam(credentials: credentials).list_roles.roles.each{ |role|
|
|
235
|
+
# match_string = "#{MU.deploy_id}.*CloudTrail"
|
|
236
|
+
# Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud.resourceClass("AWS", "Server").
|
|
237
|
+
# MU::Cloud.resourceClass("AWS", "Server").removeIAMProfile(role.role_name) if role.role_name.match(match_string)
|
|
238
|
+
# }
|
|
239
|
+
# end
|
|
237
240
|
end
|
|
238
241
|
|
|
239
242
|
# Locate an existing log group.
|
|
@@ -264,7 +267,7 @@ module MU
|
|
|
264
267
|
# Reverse-map our cloud description into a runnable config hash.
|
|
265
268
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
266
269
|
# calculate our own accordingly based on what's live in the cloud.
|
|
267
|
-
def toKitten(
|
|
270
|
+
def toKitten(**_args)
|
|
268
271
|
bok = {
|
|
269
272
|
"cloud" => "AWS",
|
|
270
273
|
"credentials" => @config['credentials'],
|
|
@@ -304,9 +307,9 @@ module MU
|
|
|
304
307
|
|
|
305
308
|
|
|
306
309
|
# Cloud-specific configuration properties.
|
|
307
|
-
# @param
|
|
310
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
308
311
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
309
|
-
def self.schema(
|
|
312
|
+
def self.schema(_config)
|
|
310
313
|
toplevel_required = []
|
|
311
314
|
schema = {
|
|
312
315
|
"retention_period" => {
|
|
@@ -357,9 +360,9 @@ module MU
|
|
|
357
360
|
|
|
358
361
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::logs}, bare and unvalidated.
|
|
359
362
|
# @param log [Hash]: The resource to process and validate
|
|
360
|
-
# @param
|
|
363
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
361
364
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
362
|
-
def self.validateConfig(log,
|
|
365
|
+
def self.validateConfig(log, _configurator)
|
|
363
366
|
ok = true
|
|
364
367
|
|
|
365
368
|
if log["filters"] && !log["filters"].empty?
|
|
@@ -53,14 +53,14 @@ module MU
|
|
|
53
53
|
new_attrs = genQueueAttrs
|
|
54
54
|
|
|
55
55
|
changed = false
|
|
56
|
-
new_attrs.each_pair { |k,
|
|
56
|
+
new_attrs.each_pair { |k, _v|
|
|
57
57
|
if !cur_attrs.has_key?(k) or cur_attrs[k] != new_attrs[k]
|
|
58
58
|
changed = true
|
|
59
59
|
end
|
|
60
60
|
}
|
|
61
61
|
if changed
|
|
62
62
|
MU.log "Updating SQS queue #{@mu_name}", MU::NOTICE, details: new_attrs
|
|
63
|
-
|
|
63
|
+
MU::Cloud::AWS.sqs(region: @config['region'], credentials: @config['credentials']).set_queue_attributes(
|
|
64
64
|
queue_url: @cloud_id,
|
|
65
65
|
attributes: new_attrs
|
|
66
66
|
)
|
|
@@ -74,10 +74,13 @@ module MU
|
|
|
74
74
|
"arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":sqs:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":"+@cloud_id
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
@cloud_desc_cache = nil
|
|
77
78
|
# Retrieve the AWS descriptor for this SQS queue. AWS doesn't exactly
|
|
78
79
|
# provide one; if you want real information for SQS ask notify()
|
|
79
80
|
# @return [Hash]: AWS doesn't return anything but the SQS URL, so supplement with attributes
|
|
80
|
-
def cloud_desc
|
|
81
|
+
def cloud_desc(use_cache: true)
|
|
82
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
83
|
+
|
|
81
84
|
if !@cloud_id
|
|
82
85
|
resp = MU::Cloud::AWS.sqs(region: @config['region'], credentials: @config['credentials']).list_queues(
|
|
83
86
|
queue_name_prefix: @mu_name
|
|
@@ -92,11 +95,12 @@ module MU
|
|
|
92
95
|
end
|
|
93
96
|
|
|
94
97
|
return nil if !@cloud_id
|
|
95
|
-
MU::Cloud::AWS::MsgQueue.find(
|
|
98
|
+
@cloud_desc_cache = MU::Cloud::AWS::MsgQueue.find(
|
|
96
99
|
cloud_id: @cloud_id.dup,
|
|
97
100
|
region: @config['region'],
|
|
98
101
|
credentials: @config['credentials']
|
|
99
102
|
)
|
|
103
|
+
@cloud_desc_cache
|
|
100
104
|
end
|
|
101
105
|
|
|
102
106
|
# Return the metadata for this MsgQueue rule
|
|
@@ -130,6 +134,9 @@ module MU
|
|
|
130
134
|
# @param region [String]: The cloud provider region
|
|
131
135
|
# @return [void]
|
|
132
136
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
137
|
+
MU.log "AWS::MsgQueue.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
138
|
+
MU.log "Placeholder: AWS MsgQueue artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
|
|
139
|
+
|
|
133
140
|
resp = MU::Cloud::AWS.sqs(credentials: credentials, region: region).list_queues(
|
|
134
141
|
queue_name_prefix: MU.deploy_id
|
|
135
142
|
)
|
|
@@ -182,7 +189,7 @@ module MU
|
|
|
182
189
|
args[:cloud_id] = resp.queue_url if resp and resp.queue_url
|
|
183
190
|
end
|
|
184
191
|
end
|
|
185
|
-
rescue ::Aws::SQS::Errors::NonExistentQueue
|
|
192
|
+
rescue ::Aws::SQS::Errors::NonExistentQueue
|
|
186
193
|
end
|
|
187
194
|
|
|
188
195
|
# Go fetch its attributes
|
|
@@ -211,9 +218,9 @@ module MU
|
|
|
211
218
|
end
|
|
212
219
|
|
|
213
220
|
# Cloud-specific configuration properties.
|
|
214
|
-
# @param
|
|
221
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
215
222
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
216
|
-
def self.schema(
|
|
223
|
+
def self.schema(_config)
|
|
217
224
|
toplevel_required = []
|
|
218
225
|
schema = {
|
|
219
226
|
"max_msg_size" => {
|
|
@@ -320,16 +327,10 @@ module MU
|
|
|
320
327
|
failq.delete("failqueue")
|
|
321
328
|
ok = false if !configurator.insertKitten(failq, "msg_queues")
|
|
322
329
|
queue['failqueue']['name'] = failq['name']
|
|
323
|
-
queue[
|
|
324
|
-
"name" => failq['name'],
|
|
325
|
-
"type" => "msg_queue"
|
|
326
|
-
}
|
|
330
|
+
MU::Config.addDependency(queue, failq["name"], "msg_queue")
|
|
327
331
|
else
|
|
328
332
|
if configurator.haveLitterMate?(queue['failqueue']['name'], "msg_queue")
|
|
329
|
-
queue['
|
|
330
|
-
"name" => queue['failqueue']['name'],
|
|
331
|
-
"type" => "msg_queue"
|
|
332
|
-
}
|
|
333
|
+
MU::Config.addDependency(queue, queue['failqueue']['name'], "msg_queue")
|
|
333
334
|
else
|
|
334
335
|
failq = MU::Cloud::AWS::MsgQueue.find(cloud_id: queue['failqueue']['name'])
|
|
335
336
|
if !failq
|
|
@@ -382,7 +383,7 @@ module MU
|
|
|
382
383
|
end
|
|
383
384
|
begin
|
|
384
385
|
MU::Cloud::AWS.kms(region: queue['region']).describe_key(key_id: queue['kms']['key_id'])
|
|
385
|
-
rescue Aws::KMS::Errors::NotFoundException
|
|
386
|
+
rescue Aws::KMS::Errors::NotFoundException
|
|
386
387
|
MU.log "KMS key '#{queue['kms']['key_id']}' specified in Queue '#{queue['name']}' was not found.", MU::ERR, details: "Key IDs are of the form bf64a093-2c3d-46fa-0d4f-8232fa7ed53. Keys can be created at https://console.aws.amazon.com/iam/home#/encryptionKeys/#{queue['region']}"
|
|
387
388
|
ok = false
|
|
388
389
|
end
|
|
@@ -164,6 +164,8 @@ module MU
|
|
|
164
164
|
# @param region [String]: The cloud provider region
|
|
165
165
|
# @return [void]
|
|
166
166
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
167
|
+
MU.log "AWS::NoSQLDb.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
168
|
+
|
|
167
169
|
resp = MU::Cloud::AWS.dynamo(credentials: credentials, region: region).list_tables
|
|
168
170
|
if resp and resp.table_names
|
|
169
171
|
resp.table_names.each { |table|
|
|
@@ -178,16 +180,23 @@ module MU
|
|
|
178
180
|
begin
|
|
179
181
|
tags = MU::Cloud::AWS.dynamo(credentials: credentials, region: region).list_tags_of_resource(resource_arn: desc.table_arn)
|
|
180
182
|
if tags and tags.tags
|
|
183
|
+
deploy_match = false
|
|
184
|
+
master_match = false
|
|
181
185
|
tags.tags.each { |tag|
|
|
182
186
|
if tag.key == "MU-ID" and tag.value == MU.deploy_id
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
end
|
|
187
|
+
deploy_match = true
|
|
188
|
+
elsif tag.key == "MU-MASTER-IP" and tag.value == MU.mu_public_ip
|
|
189
|
+
master_match = true
|
|
187
190
|
end
|
|
188
191
|
}
|
|
192
|
+
if deploy_match and (master_match or ignoremaster)
|
|
193
|
+
MU.log "Deleting DynamoDB table #{desc.table_name}"
|
|
194
|
+
if !noop
|
|
195
|
+
MU::Cloud::AWS.dynamo(credentials: credentials, region: region).delete_table(table_name: desc.table_name)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
189
198
|
end
|
|
190
|
-
rescue Aws::DynamoDB::Errors::ResourceNotFoundException
|
|
199
|
+
rescue Aws::DynamoDB::Errors::ResourceNotFoundException
|
|
191
200
|
end
|
|
192
201
|
|
|
193
202
|
}
|
|
@@ -236,9 +245,9 @@ module MU
|
|
|
236
245
|
end
|
|
237
246
|
|
|
238
247
|
# Cloud-specific configuration properties.
|
|
239
|
-
# @param
|
|
248
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
240
249
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
241
|
-
def self.schema(
|
|
250
|
+
def self.schema(_config)
|
|
242
251
|
toplevel_required = ["attributes"]
|
|
243
252
|
|
|
244
253
|
|
|
@@ -360,9 +369,9 @@ module MU
|
|
|
360
369
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::nosqldbs}, bare and unvalidated.
|
|
361
370
|
|
|
362
371
|
# @param db [Hash]: The resource to process and validate
|
|
363
|
-
# @param
|
|
372
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
364
373
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
365
|
-
def self.validateConfig(db,
|
|
374
|
+
def self.validateConfig(db, _configurator)
|
|
366
375
|
ok = true
|
|
367
376
|
|
|
368
377
|
partition = nil
|
|
@@ -399,8 +408,6 @@ module MU
|
|
|
399
408
|
ok
|
|
400
409
|
end
|
|
401
410
|
|
|
402
|
-
private
|
|
403
|
-
|
|
404
411
|
end
|
|
405
412
|
end
|
|
406
413
|
end
|
|
@@ -66,12 +66,17 @@ module MU
|
|
|
66
66
|
# @param region [String]: The cloud provider region
|
|
67
67
|
# @return [void]
|
|
68
68
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
69
|
+
MU.log "AWS::Notifier.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
70
|
+
MU.log "Placeholder: AWS Notifier artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
|
|
71
|
+
|
|
69
72
|
MU::Cloud::AWS.sns(region: region, credentials: credentials).list_topics.topics.each { |topic|
|
|
70
73
|
if topic.topic_arn.match(MU.deploy_id)
|
|
71
74
|
# We don't have a way to tag our SNS topics, so we will delete any topic that has the MU-ID in its ARN.
|
|
72
75
|
# This may fail to find notifier groups in some cases (eg. cache_cluster) so we might want to delete from each API as well.
|
|
73
|
-
MU
|
|
74
|
-
|
|
76
|
+
MU.log "Deleting SNS topic: #{topic.topic_arn}"
|
|
77
|
+
if !noop
|
|
78
|
+
MU::Cloud::AWS.sns(region: region, credentials: credentials).delete_topic(topic_arn: topic.topic_arn)
|
|
79
|
+
end
|
|
75
80
|
end
|
|
76
81
|
}
|
|
77
82
|
end
|
|
@@ -116,9 +121,9 @@ module MU
|
|
|
116
121
|
end
|
|
117
122
|
|
|
118
123
|
# Cloud-specific configuration properties.
|
|
119
|
-
# @param
|
|
124
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
120
125
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
121
|
-
def self.schema(
|
|
126
|
+
def self.schema(_config)
|
|
122
127
|
toplevel_required = []
|
|
123
128
|
schema = {
|
|
124
129
|
"subscriptions" => {
|
|
@@ -143,9 +148,9 @@ module MU
|
|
|
143
148
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::notifier}, bare and unvalidated.
|
|
144
149
|
|
|
145
150
|
# @param notifier [Hash]: The resource to process and validate
|
|
146
|
-
# @param
|
|
151
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
147
152
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
148
|
-
def self.validateConfig(notifier,
|
|
153
|
+
def self.validateConfig(notifier, _configurator)
|
|
149
154
|
ok = true
|
|
150
155
|
|
|
151
156
|
if notifier['subscriptions']
|
|
@@ -43,7 +43,7 @@ module MU
|
|
|
43
43
|
|
|
44
44
|
policy_name = @mu_name+"-"+policy.keys.first.upcase
|
|
45
45
|
MU.log "Creating IAM policy #{policy_name}"
|
|
46
|
-
|
|
46
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_policy(
|
|
47
47
|
policy_name: policy_name,
|
|
48
48
|
path: "/"+@deploy.deploy_id+"/",
|
|
49
49
|
policy_document: JSON.generate(policy.values.first),
|
|
@@ -56,8 +56,8 @@ module MU
|
|
|
56
56
|
MU.log "Creating IAM role #{@mu_name}"
|
|
57
57
|
@cloud_id = @mu_name
|
|
58
58
|
path = @config['strip_path'] ? nil : "/"+@deploy.deploy_id+"/"
|
|
59
|
-
|
|
60
|
-
path:
|
|
59
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_role(
|
|
60
|
+
path: path,
|
|
61
61
|
role_name: @mu_name,
|
|
62
62
|
description: "Generated by Mu",
|
|
63
63
|
assume_role_policy_document: gen_assume_role_policy_doc,
|
|
@@ -89,7 +89,6 @@ module MU
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
if @config['raw_policies'] or @config['attachable_policies']
|
|
92
|
-
attached_policies = []
|
|
93
92
|
configured_policies = []
|
|
94
93
|
|
|
95
94
|
if @config['raw_policies']
|
|
@@ -128,7 +127,7 @@ module MU
|
|
|
128
127
|
|
|
129
128
|
# XXX not sure we're binding these sanely, validate that
|
|
130
129
|
if @config['raw_policies']
|
|
131
|
-
|
|
130
|
+
MU::Cloud::AWS::Role.manageRawPolicies(
|
|
132
131
|
@config['raw_policies'],
|
|
133
132
|
basename: @deploy.getResourceName(@config['name']),
|
|
134
133
|
credentials: @credentials
|
|
@@ -183,7 +182,7 @@ module MU
|
|
|
183
182
|
desc
|
|
184
183
|
end
|
|
185
184
|
|
|
186
|
-
rescue Aws::IAM::Errors::NoSuchEntity
|
|
185
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
187
186
|
MU.log "Creating IAM policy #{policy_name}", details: policy.values.first
|
|
188
187
|
MU::Cloud::AWS.iam(credentials: credentials).create_policy(
|
|
189
188
|
policy_name: policy_name,
|
|
@@ -202,65 +201,72 @@ module MU
|
|
|
202
201
|
def arn
|
|
203
202
|
desc = cloud_desc
|
|
204
203
|
if desc["role"]
|
|
205
|
-
desc[
|
|
204
|
+
if desc['role'].is_a?(Hash)
|
|
205
|
+
desc["role"][:arn] # why though
|
|
206
|
+
else
|
|
207
|
+
desc["role"].arn
|
|
208
|
+
end
|
|
206
209
|
else
|
|
207
210
|
nil
|
|
208
211
|
end
|
|
209
212
|
end
|
|
210
213
|
|
|
214
|
+
@cloud_desc_cache = nil
|
|
211
215
|
# Return a hash containing a +role+ element and a +policies+ element,
|
|
212
216
|
# populated with one or both depending on what this resource has
|
|
213
217
|
# defined.
|
|
214
|
-
def cloud_desc
|
|
215
|
-
|
|
218
|
+
def cloud_desc(use_cache: true)
|
|
219
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
220
|
+
|
|
221
|
+
@cloud_desc_cache = {}
|
|
216
222
|
if @config['bare_policies']
|
|
217
223
|
if @cloud_id
|
|
218
224
|
pol_desc = MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @cloud_id).values.first
|
|
219
225
|
if pol_desc
|
|
220
|
-
|
|
221
|
-
return
|
|
226
|
+
@cloud_desc_cache['policies'] = [pol_desc]
|
|
227
|
+
return @cloud_desc_cache
|
|
222
228
|
end
|
|
223
229
|
end
|
|
224
230
|
|
|
225
231
|
if @deploy and @deploy.deploy_id
|
|
226
|
-
|
|
232
|
+
@cloud_desc_cache["policies"] = MU::Cloud::AWS.iam(credentials: @credentials).list_policies(
|
|
227
233
|
path_prefix: "/"+@deploy.deploy_id+"/"
|
|
228
234
|
).policies
|
|
229
|
-
|
|
235
|
+
@cloud_desc_cache["policies"].reject! { |p|
|
|
230
236
|
!p.policy_name.match(/^#{Regexp.quote(@mu_name)}-/)
|
|
231
237
|
}
|
|
232
238
|
# this is quasi-wrong because we can be mulitple cloud is, but
|
|
233
239
|
# we can't really set this type to has_multiples because that's
|
|
234
240
|
# just how managed policies work not anything else, goddammit
|
|
235
241
|
# AWS why can't you just bundle everything in roles
|
|
236
|
-
if
|
|
237
|
-
@cloud_id ||=
|
|
242
|
+
if @cloud_desc_cache["policies"] and @cloud_desc_cache["policies"].size > 0
|
|
243
|
+
@cloud_id ||= @cloud_desc_cache["policies"].first.arn
|
|
238
244
|
end
|
|
239
245
|
end
|
|
240
246
|
else
|
|
241
247
|
if @cloud_id.match(/^arn:aws(:?-us-gov)?:[^:]*:[^:]*:\d*:policy\//)
|
|
242
248
|
pol_desc = MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @cloud_id).values.first
|
|
243
249
|
if pol_desc
|
|
244
|
-
|
|
245
|
-
return
|
|
250
|
+
@cloud_desc_cache['policies'] = [pol_desc]
|
|
251
|
+
return @cloud_desc_cache
|
|
246
252
|
end
|
|
247
253
|
end
|
|
248
254
|
begin
|
|
249
|
-
|
|
250
|
-
|
|
255
|
+
@cloud_desc_cache['role'] = MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @cloud_id).values.first
|
|
256
|
+
@cloud_desc_cache['role'] ||= MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @mu_name).values.first
|
|
251
257
|
MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
|
|
252
258
|
role_name: @mu_name
|
|
253
259
|
).attached_policies.each { |p|
|
|
254
|
-
|
|
255
|
-
|
|
260
|
+
@cloud_desc_cache["policies"] ||= []
|
|
261
|
+
@cloud_desc_cache["policies"] << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
|
|
256
262
|
policy_arn: p.policy_arn
|
|
257
263
|
).policy
|
|
258
264
|
}
|
|
259
265
|
|
|
260
266
|
inline = MU::Cloud::AWS.iam(credentials: @credentials).list_role_policies(role_name: @mu_name).policy_names
|
|
261
267
|
inline.each { |pol_name|
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
@cloud_desc_cache["policies"] ||= []
|
|
269
|
+
@cloud_desc_cache["policies"] << MU::Cloud::AWS.iam(credentials: @credentials).get_role_policy(
|
|
264
270
|
role_name: @mu_name,
|
|
265
271
|
policy_name: pol_name
|
|
266
272
|
)
|
|
@@ -270,9 +276,9 @@ rescue ::Aws::IAM::Errors::ValidationError => e
|
|
|
270
276
|
MU.log @cloud_id+" "+@mu_name, MU::WARN, details: e.inspect
|
|
271
277
|
end
|
|
272
278
|
end
|
|
273
|
-
|
|
279
|
+
@cloud_desc_cache['cloud_id'] ||= @cloud_id
|
|
274
280
|
|
|
275
|
-
|
|
281
|
+
@cloud_desc_cache
|
|
276
282
|
end
|
|
277
283
|
|
|
278
284
|
# Return the metadata for this user cofiguration
|
|
@@ -284,26 +290,25 @@ end
|
|
|
284
290
|
# Insert a new target entity into an existing policy.
|
|
285
291
|
# @param policy [String]: The name of the policy to which we're appending, which must already exist as part of this role resource
|
|
286
292
|
# @param targets [Array<String>]: The target resource. If +target_type+ isn't specified, this should be a fully-resolved ARN.
|
|
287
|
-
|
|
288
|
-
def injectPolicyTargets(policy, targets, mu_type = nil)
|
|
293
|
+
def injectPolicyTargets(policy, targets)
|
|
289
294
|
if !policy.match(/^#{@deploy.deploy_id}/)
|
|
290
295
|
policy = @mu_name+"-"+policy.upcase
|
|
291
296
|
end
|
|
292
|
-
|
|
293
|
-
my_policies = cloud_desc["policies"]
|
|
297
|
+
my_policies = cloud_desc(use_cache: false)["policies"]
|
|
294
298
|
my_policies ||= []
|
|
295
|
-
|
|
299
|
+
|
|
300
|
+
seen_policy = false
|
|
296
301
|
my_policies.each { |p|
|
|
297
302
|
if p.policy_name == policy
|
|
303
|
+
seen_policy = true
|
|
298
304
|
old = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy_version(
|
|
299
305
|
policy_arn: p.arn,
|
|
300
306
|
version_id: p.default_version_id
|
|
301
307
|
).policy_version
|
|
302
308
|
|
|
303
309
|
doc = JSON.parse URI.decode_www_form_component old.document
|
|
304
|
-
|
|
305
310
|
need_update = false
|
|
306
|
-
|
|
311
|
+
|
|
307
312
|
doc["Statement"].each { |s|
|
|
308
313
|
targets.each { |target|
|
|
309
314
|
target_string = target
|
|
@@ -332,6 +337,10 @@ end
|
|
|
332
337
|
end
|
|
333
338
|
end
|
|
334
339
|
}
|
|
340
|
+
|
|
341
|
+
if !seen_policy
|
|
342
|
+
MU.log "Was given new targets for policy #{policy}, but I don't see any such policy attached to role #{@cloud_id}", MU::WARN, details: targets
|
|
343
|
+
end
|
|
335
344
|
end
|
|
336
345
|
|
|
337
346
|
# Delete an IAM policy, along with attendant versions and attachments.
|
|
@@ -409,9 +418,8 @@ end
|
|
|
409
418
|
# Remove all roles associated with the currently loaded deployment.
|
|
410
419
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
411
420
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
412
|
-
# @param region [String]: The cloud provider region
|
|
413
421
|
# @return [void]
|
|
414
|
-
def self.cleanup(noop: false, ignoremaster: false,
|
|
422
|
+
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
415
423
|
|
|
416
424
|
resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
|
|
417
425
|
path_prefix: "/"+MU.deploy_id+"/"
|
|
@@ -438,12 +446,18 @@ end
|
|
|
438
446
|
# check tags. Hardly seems efficient.
|
|
439
447
|
desc = MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
|
|
440
448
|
if desc.role and desc.role.tags and desc.role.tags
|
|
449
|
+
master_match = false
|
|
450
|
+
deploy_match = false
|
|
441
451
|
desc.role.tags.each { |t|
|
|
442
452
|
if t.key == "MU-ID" and t.value == MU.deploy_id
|
|
443
|
-
|
|
444
|
-
|
|
453
|
+
deploy_match = true
|
|
454
|
+
elsif t.key == "MU-MASTER-IP" and t.value == MU.mu_public_ip
|
|
455
|
+
master_match = true
|
|
445
456
|
end
|
|
446
457
|
}
|
|
458
|
+
if deploy_match and (master_match or ignoremaster)
|
|
459
|
+
deleteme << r
|
|
460
|
+
end
|
|
447
461
|
end
|
|
448
462
|
}
|
|
449
463
|
|
|
@@ -481,7 +495,7 @@ end
|
|
|
481
495
|
MU::Cloud::AWS.iam(credentials: credentials).delete_instance_profile(instance_profile_name: r.role_name)
|
|
482
496
|
rescue Aws::IAM::Errors::ValidationError => e
|
|
483
497
|
MU.log "Cleaning up IAM role #{r.role_name}: #{e.inspect}", MU::WARN
|
|
484
|
-
rescue Aws::IAM::Errors::NoSuchEntity
|
|
498
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
485
499
|
end
|
|
486
500
|
|
|
487
501
|
MU::Cloud::AWS.iam(credentials: credentials).delete_role(
|
|
@@ -519,7 +533,7 @@ end
|
|
|
519
533
|
end
|
|
520
534
|
rescue ::Aws::IAM::Errors::NoSuchEntity
|
|
521
535
|
end
|
|
522
|
-
|
|
536
|
+
|
|
523
537
|
else
|
|
524
538
|
marker = nil
|
|
525
539
|
begin
|
|
@@ -552,7 +566,7 @@ end
|
|
|
552
566
|
# Reverse-map our cloud description into a runnable config hash.
|
|
553
567
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
554
568
|
# calculate our own accordingly based on what's live in the cloud.
|
|
555
|
-
def toKitten(
|
|
569
|
+
def toKitten(**_args)
|
|
556
570
|
bok = {
|
|
557
571
|
"cloud" => "AWS",
|
|
558
572
|
"credentials" => @config['credentials'],
|
|
@@ -601,14 +615,13 @@ end
|
|
|
601
615
|
)
|
|
602
616
|
JSON.parse(URI.decode(version.policy_version.document))
|
|
603
617
|
end
|
|
604
|
-
|
|
605
618
|
bok["policies"] = MU::Cloud::AWS::Role.doc2MuPolicies(pol.policy_name, doc, bok["policies"])
|
|
606
619
|
end
|
|
607
620
|
}
|
|
608
621
|
|
|
609
622
|
return bok if @config['bare_policies']
|
|
610
623
|
end
|
|
611
|
-
|
|
624
|
+
|
|
612
625
|
if desc.tags and desc.tags.size > 0
|
|
613
626
|
bok["tags"] = MU.structToHash(desc.tags, stringify_keys: true)
|
|
614
627
|
end
|
|
@@ -681,6 +694,7 @@ end
|
|
|
681
694
|
end
|
|
682
695
|
|
|
683
696
|
bok["attachable_policies"].uniq! if bok["attachable_policies"]
|
|
697
|
+
bok["name"].gsub!(/[^a-zA-Z0-9_\-]/, "_")
|
|
684
698
|
|
|
685
699
|
bok
|
|
686
700
|
end
|
|
@@ -693,6 +707,10 @@ end
|
|
|
693
707
|
def self.doc2MuPolicies(basename, doc, policies = [])
|
|
694
708
|
policies ||= []
|
|
695
709
|
|
|
710
|
+
if !doc["Statement"].is_a?(Array)
|
|
711
|
+
doc["Statement"] = [doc["Statement"]]
|
|
712
|
+
end
|
|
713
|
+
|
|
696
714
|
doc["Statement"].each { |s|
|
|
697
715
|
if !s["Action"]
|
|
698
716
|
MU.log "Statement in policy document for #{basename} didn't have an Action field", MU::WARN, details: doc
|
|
@@ -721,7 +739,7 @@ end
|
|
|
721
739
|
"targets" => s["Resource"].map { |r|
|
|
722
740
|
if r.match(/^arn:aws(-us-gov)?:([^:]+):.*?:([^:]*)$/)
|
|
723
741
|
# XXX which cases even count for blind references to sibling resources?
|
|
724
|
-
|
|
742
|
+
if Regexp.last_match[1] == "s3"
|
|
725
743
|
"bucket"
|
|
726
744
|
elsif Regexp.last_match[1]
|
|
727
745
|
MU.log "Service #{Regexp.last_match[1]} to type...", MU::WARN, details: r
|
|
@@ -741,7 +759,7 @@ end
|
|
|
741
759
|
|
|
742
760
|
# Attach this role or group of loose policies to the specified entity.
|
|
743
761
|
# @param entitytype [String]: The type of entity (user, group or role for policies; instance_profile for roles)
|
|
744
|
-
def bindTo(entitytype, entityname
|
|
762
|
+
def bindTo(entitytype, entityname)
|
|
745
763
|
if entitytype == "instance_profile"
|
|
746
764
|
begin
|
|
747
765
|
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
|
|
@@ -754,7 +772,7 @@ end
|
|
|
754
772
|
role_name: @mu_name
|
|
755
773
|
)
|
|
756
774
|
end
|
|
757
|
-
rescue
|
|
775
|
+
rescue StandardError => e
|
|
758
776
|
MU.log "Error binding role #{@mu_name} to instance profile #{entityname}: #{e.message}", MU::ERR
|
|
759
777
|
raise e
|
|
760
778
|
end
|
|
@@ -783,7 +801,6 @@ end
|
|
|
783
801
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
|
784
802
|
if subpaths.size > 0
|
|
785
803
|
p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+policy
|
|
786
|
-
retried = true
|
|
787
804
|
retry
|
|
788
805
|
end
|
|
789
806
|
raise e
|
|
@@ -833,6 +850,7 @@ end
|
|
|
833
850
|
else
|
|
834
851
|
raise MuError, "Invalid entitytype '#{entitytype}' passed to MU::Cloud::AWS::Role.bindTo. Must be be one of: user, group, role, instance_profile"
|
|
835
852
|
end
|
|
853
|
+
cloud_desc(use_cache: false)
|
|
836
854
|
end
|
|
837
855
|
|
|
838
856
|
# Create an instance profile for EC2 instances, named identically and
|
|
@@ -847,7 +865,7 @@ end
|
|
|
847
865
|
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_instance_profile(
|
|
848
866
|
instance_profile_name: @mu_name
|
|
849
867
|
)
|
|
850
|
-
rescue Aws::IAM::Errors::EntityAlreadyExists
|
|
868
|
+
rescue Aws::IAM::Errors::EntityAlreadyExists
|
|
851
869
|
MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
|
|
852
870
|
instance_profile_name: @mu_name
|
|
853
871
|
)
|
|
@@ -905,13 +923,13 @@ end
|
|
|
905
923
|
end
|
|
906
924
|
|
|
907
925
|
# Cloud-specific configuration properties.
|
|
908
|
-
# @param
|
|
926
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
909
927
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
910
|
-
def self.schema(
|
|
928
|
+
def self.schema(_config)
|
|
911
929
|
toplevel_required = []
|
|
912
930
|
aws_resource_types = MU::Cloud.resource_types.keys.reject { |t|
|
|
913
931
|
begin
|
|
914
|
-
MU::Cloud.
|
|
932
|
+
MU::Cloud.resourceClass("AWS", t)
|
|
915
933
|
false
|
|
916
934
|
rescue MuCloudResourceNotImplemented
|
|
917
935
|
true
|
|
@@ -1012,10 +1030,9 @@ end
|
|
|
1012
1030
|
subpaths = ["service-role", "aws-service-role", "job-function"]
|
|
1013
1031
|
begin
|
|
1014
1032
|
MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
|
|
1015
|
-
rescue Aws::IAM::Errors::NoSuchEntity
|
|
1033
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
1016
1034
|
if subpaths.size > 0
|
|
1017
1035
|
arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+ref["id"]
|
|
1018
|
-
retried = true
|
|
1019
1036
|
retry
|
|
1020
1037
|
end
|
|
1021
1038
|
MU.log "No such canned AWS IAM policy '#{arn}'", MU::ERR
|
|
@@ -1029,9 +1046,9 @@ end
|
|
|
1029
1046
|
|
|
1030
1047
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::roles}, bare and unvalidated.
|
|
1031
1048
|
# @param role [Hash]: The resource to process and validate
|
|
1032
|
-
# @param
|
|
1049
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
1033
1050
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
1034
|
-
def self.validateConfig(role,
|
|
1051
|
+
def self.validateConfig(role, _configurator)
|
|
1035
1052
|
ok = true
|
|
1036
1053
|
|
|
1037
1054
|
# munge things declared with the deprecated import keyword into
|
|
@@ -1074,11 +1091,7 @@ end
|
|
|
1074
1091
|
role['policies'].each { |policy|
|
|
1075
1092
|
policy['targets'].each { |target|
|
|
1076
1093
|
if target['type']
|
|
1077
|
-
role['
|
|
1078
|
-
role['dependencies'] << {
|
|
1079
|
-
"name" => target['identifier'],
|
|
1080
|
-
"type" => target['type']
|
|
1081
|
-
}
|
|
1094
|
+
MU::Config.addDependency(role, target['identifier'], target['type'])
|
|
1082
1095
|
end
|
|
1083
1096
|
}
|
|
1084
1097
|
}
|
|
@@ -1094,9 +1107,7 @@ end
|
|
|
1094
1107
|
# @param policies [Array<Hash>]: One or more policy chunks
|
|
1095
1108
|
# @param deploy_obj [MU::MommaCat]: Deployment object to use when looking up sibling Mu resources
|
|
1096
1109
|
# @return [Array<Hash>]
|
|
1097
|
-
def self.genPolicyDocument(policies, deploy_obj: nil)
|
|
1098
|
-
iam_policies = []
|
|
1099
|
-
|
|
1110
|
+
def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false)
|
|
1100
1111
|
if policies
|
|
1101
1112
|
name = nil
|
|
1102
1113
|
doc = {
|
|
@@ -1134,12 +1145,21 @@ end
|
|
|
1134
1145
|
)
|
|
1135
1146
|
if sibling
|
|
1136
1147
|
id = sibling.cloudobj.arn
|
|
1137
|
-
|
|
1148
|
+
if bucket_style
|
|
1149
|
+
statement["Principal"] << { "AWS" => id }
|
|
1150
|
+
else
|
|
1151
|
+
statement["Principal"] << id
|
|
1152
|
+
end
|
|
1138
1153
|
else
|
|
1139
1154
|
raise MuError, "Couldn't find a #{grantee["type"]} named #{grantee["identifier"]} when generating IAM policy"
|
|
1140
1155
|
end
|
|
1141
1156
|
else
|
|
1142
|
-
|
|
1157
|
+
bucket_prefix = grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/) ? "Service" : "AWS"
|
|
1158
|
+
if bucket_style
|
|
1159
|
+
statement["Principal"] << { bucket_prefix => grantee["identifier"] }
|
|
1160
|
+
else
|
|
1161
|
+
statement["Principal"] << grantee["identifier"]
|
|
1162
|
+
end
|
|
1143
1163
|
end
|
|
1144
1164
|
}
|
|
1145
1165
|
if policy["grant_to"].size == 1
|
|
@@ -1162,9 +1182,11 @@ end
|
|
|
1162
1182
|
stream_id = id.sub(/:([^:]+)$/, ":log-stream:*")
|
|
1163
1183
|
# "arn:aws:logs:us-east-2:accountID:log-group:log_group_name:log-stream:CloudTrail_log_stream_name_prefix*"
|
|
1164
1184
|
statement["Resource"] << stream_id
|
|
1185
|
+
elsif id.match(/:s3:/)
|
|
1186
|
+
statement["Resource"] << id+"/*"
|
|
1165
1187
|
end
|
|
1166
1188
|
else
|
|
1167
|
-
raise MuError, "Couldn't find a #{target["
|
|
1189
|
+
raise MuError, "Couldn't find a #{target["type"]} named #{target["identifier"]} when generating IAM policy"
|
|
1168
1190
|
end
|
|
1169
1191
|
else
|
|
1170
1192
|
target["identifier"] += target["path"] if target["path"]
|
|
@@ -1180,6 +1202,32 @@ end
|
|
|
1180
1202
|
[]
|
|
1181
1203
|
end
|
|
1182
1204
|
|
|
1205
|
+
# Update a policy, handling deletion of old versions as needed
|
|
1206
|
+
# @param arn [String]:
|
|
1207
|
+
# @param doc [Hash]:
|
|
1208
|
+
# @param credentials [String]:
|
|
1209
|
+
def self.update_policy(arn, doc, credentials: nil)
|
|
1210
|
+
# XXX this is just blindly replacing identical versions, when it should check
|
|
1211
|
+
# and guard
|
|
1212
|
+
begin
|
|
1213
|
+
MU::Cloud::AWS.iam(credentials: credentials).create_policy_version(
|
|
1214
|
+
policy_arn: arn,
|
|
1215
|
+
set_as_default: true,
|
|
1216
|
+
policy_document: JSON.generate(doc)
|
|
1217
|
+
)
|
|
1218
|
+
rescue Aws::IAM::Errors::LimitExceeded
|
|
1219
|
+
delete_version = MU::Cloud::AWS.iam(credentials: credentials).list_policy_versions(
|
|
1220
|
+
policy_arn: arn,
|
|
1221
|
+
).versions.last.version_id
|
|
1222
|
+
MU.log "Purging oldest version (#{delete_version}) of IAM policy #{arn}", MU::NOTICE
|
|
1223
|
+
MU::Cloud::AWS.iam(credentials: credentials).delete_policy_version(
|
|
1224
|
+
policy_arn: arn,
|
|
1225
|
+
version_id: delete_version
|
|
1226
|
+
)
|
|
1227
|
+
retry
|
|
1228
|
+
end
|
|
1229
|
+
end
|
|
1230
|
+
|
|
1183
1231
|
private
|
|
1184
1232
|
|
|
1185
1233
|
# Convert entries from the cloud-neutral @config['policies'] list into
|
|
@@ -1261,28 +1309,6 @@ end
|
|
|
1261
1309
|
MU::Cloud::AWS::Role.update_policy(arn, doc, credentials: @credentials)
|
|
1262
1310
|
end
|
|
1263
1311
|
|
|
1264
|
-
# Update a policy, handling deletion of old versions as needed
|
|
1265
|
-
def self.update_policy(arn, doc, credentials: nil)
|
|
1266
|
-
# XXX this is just blindly replacing identical versions, when it should check
|
|
1267
|
-
# and guard
|
|
1268
|
-
begin
|
|
1269
|
-
MU::Cloud::AWS.iam(credentials: credentials).create_policy_version(
|
|
1270
|
-
policy_arn: arn,
|
|
1271
|
-
set_as_default: true,
|
|
1272
|
-
policy_document: JSON.generate(doc)
|
|
1273
|
-
)
|
|
1274
|
-
rescue Aws::IAM::Errors::LimitExceeded => e
|
|
1275
|
-
delete_version = MU::Cloud::AWS.iam(credentials: credentials).list_policy_versions(
|
|
1276
|
-
policy_arn: arn,
|
|
1277
|
-
).versions.last.version_id
|
|
1278
|
-
MU.log "Purging oldest version (#{delete_version}) of IAM policy #{arn}", MU::NOTICE
|
|
1279
|
-
MU::Cloud::AWS.iam(credentials: credentials).delete_policy_version(
|
|
1280
|
-
policy_arn: arn,
|
|
1281
|
-
version_id: delete_version
|
|
1282
|
-
)
|
|
1283
|
-
retry
|
|
1284
|
-
end
|
|
1285
|
-
end
|
|
1286
1312
|
|
|
1287
1313
|
end
|
|
1288
1314
|
end
|