cloud-mu 3.1.3 → 3.1.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/Dockerfile +10 -2
- data/bin/mu-adopt +5 -1
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-run-tests +112 -27
- data/cloud-mu.gemspec +20 -20
- data/cookbooks/mu-tools/libraries/helper.rb +2 -1
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +5 -15
- data/modules/mu.rb +10 -14
- data/modules/mu/adoption.rb +20 -14
- data/modules/mu/cleanup.rb +13 -9
- data/modules/mu/cloud.rb +26 -26
- data/modules/mu/clouds/aws.rb +100 -59
- data/modules/mu/clouds/aws/alarm.rb +4 -2
- data/modules/mu/clouds/aws/bucket.rb +25 -21
- data/modules/mu/clouds/aws/cache_cluster.rb +25 -23
- data/modules/mu/clouds/aws/collection.rb +21 -20
- data/modules/mu/clouds/aws/container_cluster.rb +47 -26
- data/modules/mu/clouds/aws/database.rb +57 -68
- data/modules/mu/clouds/aws/dnszone.rb +14 -14
- data/modules/mu/clouds/aws/endpoint.rb +20 -16
- data/modules/mu/clouds/aws/firewall_rule.rb +19 -16
- data/modules/mu/clouds/aws/folder.rb +7 -7
- data/modules/mu/clouds/aws/function.rb +15 -12
- data/modules/mu/clouds/aws/group.rb +14 -10
- data/modules/mu/clouds/aws/habitat.rb +16 -13
- data/modules/mu/clouds/aws/loadbalancer.rb +16 -15
- data/modules/mu/clouds/aws/log.rb +13 -10
- data/modules/mu/clouds/aws/msg_queue.rb +15 -8
- data/modules/mu/clouds/aws/nosqldb.rb +18 -11
- data/modules/mu/clouds/aws/notifier.rb +11 -6
- data/modules/mu/clouds/aws/role.rb +87 -70
- data/modules/mu/clouds/aws/search_domain.rb +30 -19
- data/modules/mu/clouds/aws/server.rb +102 -72
- data/modules/mu/clouds/aws/server_pool.rb +47 -28
- data/modules/mu/clouds/aws/storage_pool.rb +5 -6
- data/modules/mu/clouds/aws/user.rb +13 -10
- data/modules/mu/clouds/aws/vpc.rb +135 -121
- data/modules/mu/clouds/azure.rb +16 -9
- data/modules/mu/clouds/azure/container_cluster.rb +2 -3
- data/modules/mu/clouds/azure/firewall_rule.rb +10 -10
- data/modules/mu/clouds/azure/habitat.rb +8 -6
- data/modules/mu/clouds/azure/loadbalancer.rb +5 -5
- data/modules/mu/clouds/azure/role.rb +8 -10
- data/modules/mu/clouds/azure/server.rb +65 -25
- data/modules/mu/clouds/azure/user.rb +5 -7
- data/modules/mu/clouds/azure/vpc.rb +12 -15
- data/modules/mu/clouds/cloudformation.rb +8 -7
- data/modules/mu/clouds/cloudformation/vpc.rb +2 -4
- data/modules/mu/clouds/google.rb +39 -24
- data/modules/mu/clouds/google/bucket.rb +9 -11
- data/modules/mu/clouds/google/container_cluster.rb +27 -42
- data/modules/mu/clouds/google/database.rb +6 -9
- data/modules/mu/clouds/google/firewall_rule.rb +11 -10
- data/modules/mu/clouds/google/folder.rb +16 -9
- data/modules/mu/clouds/google/function.rb +127 -161
- data/modules/mu/clouds/google/group.rb +21 -18
- data/modules/mu/clouds/google/habitat.rb +18 -15
- data/modules/mu/clouds/google/loadbalancer.rb +14 -16
- data/modules/mu/clouds/google/role.rb +48 -31
- data/modules/mu/clouds/google/server.rb +105 -105
- data/modules/mu/clouds/google/server_pool.rb +12 -31
- data/modules/mu/clouds/google/user.rb +67 -13
- data/modules/mu/clouds/google/vpc.rb +58 -65
- data/modules/mu/config.rb +89 -1738
- data/modules/mu/config/bucket.rb +3 -3
- data/modules/mu/config/collection.rb +3 -3
- data/modules/mu/config/container_cluster.rb +2 -2
- data/modules/mu/config/dnszone.rb +5 -5
- data/modules/mu/config/doc_helpers.rb +517 -0
- data/modules/mu/config/endpoint.rb +3 -3
- data/modules/mu/config/firewall_rule.rb +118 -3
- data/modules/mu/config/folder.rb +3 -3
- data/modules/mu/config/function.rb +2 -2
- data/modules/mu/config/group.rb +3 -3
- data/modules/mu/config/habitat.rb +3 -3
- data/modules/mu/config/loadbalancer.rb +3 -3
- data/modules/mu/config/log.rb +3 -3
- data/modules/mu/config/msg_queue.rb +3 -3
- data/modules/mu/config/nosqldb.rb +3 -3
- data/modules/mu/config/notifier.rb +2 -2
- data/modules/mu/config/ref.rb +333 -0
- data/modules/mu/config/role.rb +3 -3
- data/modules/mu/config/schema_helpers.rb +508 -0
- data/modules/mu/config/search_domain.rb +3 -3
- data/modules/mu/config/server.rb +86 -58
- data/modules/mu/config/server_pool.rb +2 -2
- data/modules/mu/config/tail.rb +189 -0
- data/modules/mu/config/user.rb +3 -3
- data/modules/mu/config/vpc.rb +44 -4
- data/modules/mu/defaults/Google.yaml +2 -2
- data/modules/mu/deploy.rb +13 -10
- data/modules/mu/groomer.rb +1 -1
- data/modules/mu/groomers/ansible.rb +69 -24
- data/modules/mu/groomers/chef.rb +52 -44
- data/modules/mu/logger.rb +17 -14
- data/modules/mu/master.rb +317 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -2
- data/modules/mu/mommacat.rb +85 -1766
- data/modules/mu/mommacat/daemon.rb +394 -0
- data/modules/mu/mommacat/naming.rb +366 -0
- data/modules/mu/mommacat/storage.rb +689 -0
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/{win2k12.yaml → needwork/win2k12.yaml} +0 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- metadata +112 -102
|
@@ -45,7 +45,6 @@ module MU
|
|
|
45
45
|
resp = MU::Cloud::AWS.orgs(credentials: @config['credentials']).describe_create_account_status(
|
|
46
46
|
create_account_request_id: createid
|
|
47
47
|
)
|
|
48
|
-
createstatus = resp.create_account_status.state
|
|
49
48
|
if !["SUCCEEDED", "IN_PROGRESS"].include?(resp.create_account_status.state)
|
|
50
49
|
raise MuError, "Failed to create account #{@mu_name}: #{resp.create_account_status.failure_reason}"
|
|
51
50
|
end
|
|
@@ -59,9 +58,12 @@ module MU
|
|
|
59
58
|
MU.log "Creation of account #{@mu_name} (#{resp.create_account_status.account_id}) complete"
|
|
60
59
|
end
|
|
61
60
|
|
|
61
|
+
@cloud_desc_cache = nil
|
|
62
62
|
# Return the cloud descriptor for the Habitat
|
|
63
|
-
def cloud_desc
|
|
64
|
-
|
|
63
|
+
def cloud_desc(use_cache: true)
|
|
64
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
65
|
+
@cloud_desc_cache = MU::Cloud::AWS::Habitat.find(cloud_id: @cloud_id).values.first
|
|
66
|
+
@cloud_desc_cache
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
# Canonical Amazon Resource Number for this resource
|
|
@@ -87,10 +89,11 @@ module MU
|
|
|
87
89
|
# Remove all AWS accounts associated with the currently loaded deployment. Try to, anyway.
|
|
88
90
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
89
91
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
90
|
-
# @param region [String]: The cloud provider region
|
|
91
92
|
# @return [void]
|
|
92
|
-
def self.cleanup(noop: false, ignoremaster: false,
|
|
93
|
+
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
93
94
|
return if !orgMasterCreds?(credentials)
|
|
95
|
+
MU.log "AWS::Habitat.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
96
|
+
MU.log "Placeholder: AWS Habitat artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
|
|
94
97
|
|
|
95
98
|
resp = MU::Cloud::AWS.orgs(credentials: credentials).list_accounts
|
|
96
99
|
|
|
@@ -108,14 +111,14 @@ module MU
|
|
|
108
111
|
|
|
109
112
|
# Locate an existing account
|
|
110
113
|
# @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching account
|
|
111
|
-
def self.find(**
|
|
114
|
+
def self.find(**_args)
|
|
112
115
|
{}
|
|
113
116
|
end
|
|
114
117
|
|
|
115
118
|
# Cloud-specific configuration properties.
|
|
116
|
-
# @param
|
|
119
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
117
120
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
118
|
-
def self.schema(
|
|
121
|
+
def self.schema(_config)
|
|
119
122
|
toplevel_required = []
|
|
120
123
|
schema = {
|
|
121
124
|
"email" => {
|
|
@@ -126,9 +129,10 @@ module MU
|
|
|
126
129
|
[toplevel_required, schema]
|
|
127
130
|
end
|
|
128
131
|
|
|
129
|
-
# @param
|
|
132
|
+
# @param _account_number [String]
|
|
133
|
+
# @param _credentials [String]
|
|
130
134
|
# @return [Boolean]
|
|
131
|
-
def self.isLive?(
|
|
135
|
+
def self.isLive?(_account_number, _credentials = nil)
|
|
132
136
|
true
|
|
133
137
|
end
|
|
134
138
|
|
|
@@ -138,7 +142,6 @@ module MU
|
|
|
138
142
|
# @param credentials [String]
|
|
139
143
|
# @return [Boolean]
|
|
140
144
|
def self.orgMasterCreds?(credentials = nil)
|
|
141
|
-
user_list = MU::Cloud::AWS.iam(credentials: credentials).list_users.users
|
|
142
145
|
acct_num = MU::Cloud::AWS.iam(credentials: credentials).list_users.users.first.arn.split(/:/)[4]
|
|
143
146
|
|
|
144
147
|
parentorg = MU::Cloud::AWS::Folder.find(credentials: credentials).values.first
|
|
@@ -147,9 +150,9 @@ module MU
|
|
|
147
150
|
|
|
148
151
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::habitats}, bare and unvalidated.
|
|
149
152
|
# @param habitat [Hash]: The resource to process and validate
|
|
150
|
-
# @param
|
|
153
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
151
154
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
152
|
-
def self.validateConfig(habitat,
|
|
155
|
+
def self.validateConfig(habitat, _configurator)
|
|
153
156
|
ok = true
|
|
154
157
|
|
|
155
158
|
if !habitat["email"]
|
|
@@ -288,7 +288,7 @@ module MU
|
|
|
288
288
|
else
|
|
289
289
|
@config["listeners"].each { |l|
|
|
290
290
|
if l['ssl_certificate_id']
|
|
291
|
-
|
|
291
|
+
MU::Cloud::AWS.elb(region: @config['region'], credentials: @config['credentials']).set_load_balancer_policies_of_listener(
|
|
292
292
|
load_balancer_name: @cloud_id,
|
|
293
293
|
load_balancer_port: l['lb_port'],
|
|
294
294
|
policy_names: [
|
|
@@ -330,7 +330,7 @@ module MU
|
|
|
330
330
|
}
|
|
331
331
|
)
|
|
332
332
|
else
|
|
333
|
-
@targetgroups.
|
|
333
|
+
@targetgroups.values.each { |tg|
|
|
334
334
|
MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).modify_target_group_attributes(
|
|
335
335
|
target_group_arn: tg.target_group_arn,
|
|
336
336
|
attributes: [
|
|
@@ -400,7 +400,7 @@ module MU
|
|
|
400
400
|
timeout = 0
|
|
401
401
|
MU.log "Disabling connection draining on #{lb.dns_name}"
|
|
402
402
|
end
|
|
403
|
-
@targetgroups.
|
|
403
|
+
@targetgroups.values.each { |tg|
|
|
404
404
|
MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).modify_target_group_attributes(
|
|
405
405
|
target_group_arn: tg.target_group_arn,
|
|
406
406
|
attributes: [
|
|
@@ -473,7 +473,7 @@ module MU
|
|
|
473
473
|
end
|
|
474
474
|
end
|
|
475
475
|
else
|
|
476
|
-
@targetgroups.
|
|
476
|
+
@targetgroups.values.each { |tg|
|
|
477
477
|
MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).modify_target_group_attributes(
|
|
478
478
|
target_group_arn: tg.target_group_arn,
|
|
479
479
|
attributes: [
|
|
@@ -553,15 +553,17 @@ module MU
|
|
|
553
553
|
end
|
|
554
554
|
end
|
|
555
555
|
|
|
556
|
+
@cloud_desc_cache = nil
|
|
556
557
|
# Wrapper for cloud_desc method that deals with elb vs. elb2 resources.
|
|
557
|
-
def cloud_desc
|
|
558
|
+
def cloud_desc(use_cache: true)
|
|
559
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
558
560
|
if @config['classic']
|
|
559
|
-
|
|
561
|
+
@cloud_desc_cache = MU::Cloud::AWS.elb(region: @config['region'], credentials: @config['credentials']).describe_load_balancers(
|
|
560
562
|
load_balancer_names: [@cloud_id]
|
|
561
563
|
).load_balancer_descriptions.first
|
|
562
|
-
return
|
|
564
|
+
return @cloud_desc_cache
|
|
563
565
|
else
|
|
564
|
-
|
|
566
|
+
@cloud_desc_cache = MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_load_balancers(
|
|
565
567
|
names: [@cloud_id]
|
|
566
568
|
).load_balancers.first
|
|
567
569
|
if @targetgroups.nil? and !@deploy.nil? and
|
|
@@ -573,7 +575,7 @@ module MU
|
|
|
573
575
|
}
|
|
574
576
|
end
|
|
575
577
|
|
|
576
|
-
return
|
|
578
|
+
return @cloud_desc_cache
|
|
577
579
|
end
|
|
578
580
|
end
|
|
579
581
|
|
|
@@ -692,7 +694,6 @@ module MU
|
|
|
692
694
|
classic = false
|
|
693
695
|
end
|
|
694
696
|
begin
|
|
695
|
-
tags = []
|
|
696
697
|
matched = false
|
|
697
698
|
if flags and flags['vpc_id']
|
|
698
699
|
matched = true if lb.vpc_id == flags['vpc_id']
|
|
@@ -773,9 +774,9 @@ module MU
|
|
|
773
774
|
end
|
|
774
775
|
|
|
775
776
|
# Cloud-specific configuration properties.
|
|
776
|
-
# @param
|
|
777
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
777
778
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
778
|
-
def self.schema(
|
|
779
|
+
def self.schema(_config)
|
|
779
780
|
toplevel_required = []
|
|
780
781
|
schema = {
|
|
781
782
|
"targetgroups" => {
|
|
@@ -818,9 +819,9 @@ module MU
|
|
|
818
819
|
|
|
819
820
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::loadbalancers}, bare and unvalidated.
|
|
820
821
|
# @param lb [Hash]: The resource to process and validate
|
|
821
|
-
# @param
|
|
822
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
822
823
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
823
|
-
def self.validateConfig(lb,
|
|
824
|
+
def self.validateConfig(lb, _configurator)
|
|
824
825
|
ok = true
|
|
825
826
|
|
|
826
827
|
# XXX what about raw targetgroup ssl declarations?
|
|
@@ -830,7 +831,7 @@ module MU
|
|
|
830
831
|
if lb['cloud'] != "CloudFormation" # XXX or maybe do this anyway?
|
|
831
832
|
begin
|
|
832
833
|
listener["ssl_certificate_id"] = MU::Cloud::AWS.findSSLCertificate(name: listener["ssl_certificate_name"].to_s, id: listener["ssl_certificate_id"].to_s, region: lb['region'])
|
|
833
|
-
rescue MuError
|
|
834
|
+
rescue MuError
|
|
834
835
|
ok = false
|
|
835
836
|
next
|
|
836
837
|
end
|
|
@@ -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
|
+
# unless noop
|
|
234
|
+
# MU::Cloud::AWS.iam(credentials: credentials).list_roles.roles.each{ |role|
|
|
235
|
+
# match_string = "#{MU.deploy_id}.*CloudTrail"
|
|
233
236
|
# Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud::AWS::Server.
|
|
234
237
|
# MU::Cloud::AWS::Server.removeIAMProfile(role.role_name) if role.role_name.match(match_string)
|
|
235
|
-
}
|
|
236
|
-
end
|
|
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" => {
|
|
@@ -382,7 +389,7 @@ module MU
|
|
|
382
389
|
end
|
|
383
390
|
begin
|
|
384
391
|
MU::Cloud::AWS.kms(region: queue['region']).describe_key(key_id: queue['kms']['key_id'])
|
|
385
|
-
rescue Aws::KMS::Errors::NotFoundException
|
|
392
|
+
rescue Aws::KMS::Errors::NotFoundException
|
|
386
393
|
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
394
|
ok = false
|
|
388
395
|
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,
|
|
@@ -208,59 +207,62 @@ module MU
|
|
|
208
207
|
end
|
|
209
208
|
end
|
|
210
209
|
|
|
210
|
+
@cloud_desc_cache = nil
|
|
211
211
|
# Return a hash containing a +role+ element and a +policies+ element,
|
|
212
212
|
# populated with one or both depending on what this resource has
|
|
213
213
|
# defined.
|
|
214
|
-
def cloud_desc
|
|
215
|
-
|
|
214
|
+
def cloud_desc(use_cache: true)
|
|
215
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
216
|
+
|
|
217
|
+
@cloud_desc_cache = {}
|
|
216
218
|
if @config['bare_policies']
|
|
217
219
|
if @cloud_id
|
|
218
220
|
pol_desc = MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @cloud_id).values.first
|
|
219
221
|
if pol_desc
|
|
220
|
-
|
|
221
|
-
return
|
|
222
|
+
@cloud_desc_cache['policies'] = [pol_desc]
|
|
223
|
+
return @cloud_desc_cache
|
|
222
224
|
end
|
|
223
225
|
end
|
|
224
226
|
|
|
225
227
|
if @deploy and @deploy.deploy_id
|
|
226
|
-
|
|
228
|
+
@cloud_desc_cache["policies"] = MU::Cloud::AWS.iam(credentials: @credentials).list_policies(
|
|
227
229
|
path_prefix: "/"+@deploy.deploy_id+"/"
|
|
228
230
|
).policies
|
|
229
|
-
|
|
231
|
+
@cloud_desc_cache["policies"].reject! { |p|
|
|
230
232
|
!p.policy_name.match(/^#{Regexp.quote(@mu_name)}-/)
|
|
231
233
|
}
|
|
232
234
|
# this is quasi-wrong because we can be mulitple cloud is, but
|
|
233
235
|
# we can't really set this type to has_multiples because that's
|
|
234
236
|
# just how managed policies work not anything else, goddammit
|
|
235
237
|
# AWS why can't you just bundle everything in roles
|
|
236
|
-
if
|
|
237
|
-
@cloud_id ||=
|
|
238
|
+
if @cloud_desc_cache["policies"] and @cloud_desc_cache["policies"].size > 0
|
|
239
|
+
@cloud_id ||= @cloud_desc_cache["policies"].first.arn
|
|
238
240
|
end
|
|
239
241
|
end
|
|
240
242
|
else
|
|
241
243
|
if @cloud_id.match(/^arn:aws(:?-us-gov)?:[^:]*:[^:]*:\d*:policy\//)
|
|
242
244
|
pol_desc = MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @cloud_id).values.first
|
|
243
245
|
if pol_desc
|
|
244
|
-
|
|
245
|
-
return
|
|
246
|
+
@cloud_desc_cache['policies'] = [pol_desc]
|
|
247
|
+
return @cloud_desc_cache
|
|
246
248
|
end
|
|
247
249
|
end
|
|
248
250
|
begin
|
|
249
|
-
|
|
250
|
-
|
|
251
|
+
@cloud_desc_cache['role'] = MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @cloud_id).values.first
|
|
252
|
+
@cloud_desc_cache['role'] ||= MU::Cloud::AWS::Role.find(credentials: @credentials, cloud_id: @mu_name).values.first
|
|
251
253
|
MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
|
|
252
254
|
role_name: @mu_name
|
|
253
255
|
).attached_policies.each { |p|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
+
@cloud_desc_cache["policies"] ||= []
|
|
257
|
+
@cloud_desc_cache["policies"] << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
|
|
256
258
|
policy_arn: p.policy_arn
|
|
257
259
|
).policy
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
inline = MU::Cloud::AWS.iam(credentials: @credentials).list_role_policies(role_name: @mu_name).policy_names
|
|
261
263
|
inline.each { |pol_name|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
+
@cloud_desc_cache["policies"] ||= []
|
|
265
|
+
@cloud_desc_cache["policies"] << MU::Cloud::AWS.iam(credentials: @credentials).get_role_policy(
|
|
264
266
|
role_name: @mu_name,
|
|
265
267
|
policy_name: pol_name
|
|
266
268
|
)
|
|
@@ -270,9 +272,9 @@ rescue ::Aws::IAM::Errors::ValidationError => e
|
|
|
270
272
|
MU.log @cloud_id+" "+@mu_name, MU::WARN, details: e.inspect
|
|
271
273
|
end
|
|
272
274
|
end
|
|
273
|
-
|
|
275
|
+
@cloud_desc_cache['cloud_id'] ||= @cloud_id
|
|
274
276
|
|
|
275
|
-
|
|
277
|
+
@cloud_desc_cache
|
|
276
278
|
end
|
|
277
279
|
|
|
278
280
|
# Return the metadata for this user cofiguration
|
|
@@ -284,8 +286,7 @@ end
|
|
|
284
286
|
# Insert a new target entity into an existing policy.
|
|
285
287
|
# @param policy [String]: The name of the policy to which we're appending, which must already exist as part of this role resource
|
|
286
288
|
# @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)
|
|
289
|
+
def injectPolicyTargets(policy, targets)
|
|
289
290
|
if !policy.match(/^#{@deploy.deploy_id}/)
|
|
290
291
|
policy = @mu_name+"-"+policy.upcase
|
|
291
292
|
end
|
|
@@ -409,9 +410,8 @@ end
|
|
|
409
410
|
# Remove all roles associated with the currently loaded deployment.
|
|
410
411
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
411
412
|
# @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
413
|
# @return [void]
|
|
414
|
-
def self.cleanup(noop: false, ignoremaster: false,
|
|
414
|
+
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
415
415
|
|
|
416
416
|
resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
|
|
417
417
|
path_prefix: "/"+MU.deploy_id+"/"
|
|
@@ -438,12 +438,18 @@ end
|
|
|
438
438
|
# check tags. Hardly seems efficient.
|
|
439
439
|
desc = MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
|
|
440
440
|
if desc.role and desc.role.tags and desc.role.tags
|
|
441
|
+
master_match = false
|
|
442
|
+
deploy_match = false
|
|
441
443
|
desc.role.tags.each { |t|
|
|
442
444
|
if t.key == "MU-ID" and t.value == MU.deploy_id
|
|
443
|
-
|
|
444
|
-
|
|
445
|
+
deploy_match = true
|
|
446
|
+
elsif t.key == "MU-MASTER-IP" and t.value == MU.mu_public_ip
|
|
447
|
+
master_match = true
|
|
445
448
|
end
|
|
446
449
|
}
|
|
450
|
+
if deploy_match and (master_match or ignoremaster)
|
|
451
|
+
deleteme << r
|
|
452
|
+
end
|
|
447
453
|
end
|
|
448
454
|
}
|
|
449
455
|
|
|
@@ -481,7 +487,7 @@ end
|
|
|
481
487
|
MU::Cloud::AWS.iam(credentials: credentials).delete_instance_profile(instance_profile_name: r.role_name)
|
|
482
488
|
rescue Aws::IAM::Errors::ValidationError => e
|
|
483
489
|
MU.log "Cleaning up IAM role #{r.role_name}: #{e.inspect}", MU::WARN
|
|
484
|
-
rescue Aws::IAM::Errors::NoSuchEntity
|
|
490
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
485
491
|
end
|
|
486
492
|
|
|
487
493
|
MU::Cloud::AWS.iam(credentials: credentials).delete_role(
|
|
@@ -552,7 +558,7 @@ end
|
|
|
552
558
|
# Reverse-map our cloud description into a runnable config hash.
|
|
553
559
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
554
560
|
# calculate our own accordingly based on what's live in the cloud.
|
|
555
|
-
def toKitten(
|
|
561
|
+
def toKitten(**_args)
|
|
556
562
|
bok = {
|
|
557
563
|
"cloud" => "AWS",
|
|
558
564
|
"credentials" => @config['credentials'],
|
|
@@ -721,7 +727,7 @@ end
|
|
|
721
727
|
"targets" => s["Resource"].map { |r|
|
|
722
728
|
if r.match(/^arn:aws(-us-gov)?:([^:]+):.*?:([^:]*)$/)
|
|
723
729
|
# XXX which cases even count for blind references to sibling resources?
|
|
724
|
-
|
|
730
|
+
if Regexp.last_match[1] == "s3"
|
|
725
731
|
"bucket"
|
|
726
732
|
elsif Regexp.last_match[1]
|
|
727
733
|
MU.log "Service #{Regexp.last_match[1]} to type...", MU::WARN, details: r
|
|
@@ -741,7 +747,7 @@ end
|
|
|
741
747
|
|
|
742
748
|
# Attach this role or group of loose policies to the specified entity.
|
|
743
749
|
# @param entitytype [String]: The type of entity (user, group or role for policies; instance_profile for roles)
|
|
744
|
-
def bindTo(entitytype, entityname
|
|
750
|
+
def bindTo(entitytype, entityname)
|
|
745
751
|
if entitytype == "instance_profile"
|
|
746
752
|
begin
|
|
747
753
|
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
|
|
@@ -754,7 +760,7 @@ end
|
|
|
754
760
|
role_name: @mu_name
|
|
755
761
|
)
|
|
756
762
|
end
|
|
757
|
-
rescue
|
|
763
|
+
rescue StandardError => e
|
|
758
764
|
MU.log "Error binding role #{@mu_name} to instance profile #{entityname}: #{e.message}", MU::ERR
|
|
759
765
|
raise e
|
|
760
766
|
end
|
|
@@ -783,7 +789,6 @@ end
|
|
|
783
789
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
|
784
790
|
if subpaths.size > 0
|
|
785
791
|
p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+policy
|
|
786
|
-
retried = true
|
|
787
792
|
retry
|
|
788
793
|
end
|
|
789
794
|
raise e
|
|
@@ -847,7 +852,7 @@ end
|
|
|
847
852
|
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_instance_profile(
|
|
848
853
|
instance_profile_name: @mu_name
|
|
849
854
|
)
|
|
850
|
-
rescue Aws::IAM::Errors::EntityAlreadyExists
|
|
855
|
+
rescue Aws::IAM::Errors::EntityAlreadyExists
|
|
851
856
|
MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
|
|
852
857
|
instance_profile_name: @mu_name
|
|
853
858
|
)
|
|
@@ -905,9 +910,9 @@ end
|
|
|
905
910
|
end
|
|
906
911
|
|
|
907
912
|
# Cloud-specific configuration properties.
|
|
908
|
-
# @param
|
|
913
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
909
914
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
910
|
-
def self.schema(
|
|
915
|
+
def self.schema(_config)
|
|
911
916
|
toplevel_required = []
|
|
912
917
|
aws_resource_types = MU::Cloud.resource_types.keys.reject { |t|
|
|
913
918
|
begin
|
|
@@ -1012,10 +1017,9 @@ end
|
|
|
1012
1017
|
subpaths = ["service-role", "aws-service-role", "job-function"]
|
|
1013
1018
|
begin
|
|
1014
1019
|
MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
|
|
1015
|
-
rescue Aws::IAM::Errors::NoSuchEntity
|
|
1020
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
1016
1021
|
if subpaths.size > 0
|
|
1017
1022
|
arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+ref["id"]
|
|
1018
|
-
retried = true
|
|
1019
1023
|
retry
|
|
1020
1024
|
end
|
|
1021
1025
|
MU.log "No such canned AWS IAM policy '#{arn}'", MU::ERR
|
|
@@ -1029,9 +1033,9 @@ end
|
|
|
1029
1033
|
|
|
1030
1034
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::roles}, bare and unvalidated.
|
|
1031
1035
|
# @param role [Hash]: The resource to process and validate
|
|
1032
|
-
# @param
|
|
1036
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
1033
1037
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
1034
|
-
def self.validateConfig(role,
|
|
1038
|
+
def self.validateConfig(role, _configurator)
|
|
1035
1039
|
ok = true
|
|
1036
1040
|
|
|
1037
1041
|
# munge things declared with the deprecated import keyword into
|
|
@@ -1094,9 +1098,7 @@ end
|
|
|
1094
1098
|
# @param policies [Array<Hash>]: One or more policy chunks
|
|
1095
1099
|
# @param deploy_obj [MU::MommaCat]: Deployment object to use when looking up sibling Mu resources
|
|
1096
1100
|
# @return [Array<Hash>]
|
|
1097
|
-
def self.genPolicyDocument(policies, deploy_obj: nil)
|
|
1098
|
-
iam_policies = []
|
|
1099
|
-
|
|
1101
|
+
def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false)
|
|
1100
1102
|
if policies
|
|
1101
1103
|
name = nil
|
|
1102
1104
|
doc = {
|
|
@@ -1134,12 +1136,21 @@ end
|
|
|
1134
1136
|
)
|
|
1135
1137
|
if sibling
|
|
1136
1138
|
id = sibling.cloudobj.arn
|
|
1137
|
-
|
|
1139
|
+
if bucket_style
|
|
1140
|
+
statement["Principal"] << { "AWS" => id }
|
|
1141
|
+
else
|
|
1142
|
+
statement["Principal"] << id
|
|
1143
|
+
end
|
|
1138
1144
|
else
|
|
1139
1145
|
raise MuError, "Couldn't find a #{grantee["type"]} named #{grantee["identifier"]} when generating IAM policy"
|
|
1140
1146
|
end
|
|
1141
1147
|
else
|
|
1142
|
-
|
|
1148
|
+
bucket_prefix = grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/) ? "Service" : "AWS"
|
|
1149
|
+
if bucket_style
|
|
1150
|
+
statement["Principal"] << { bucket_prefix => grantee["identifier"] }
|
|
1151
|
+
else
|
|
1152
|
+
statement["Principal"] << grantee["identifier"]
|
|
1153
|
+
end
|
|
1143
1154
|
end
|
|
1144
1155
|
}
|
|
1145
1156
|
if policy["grant_to"].size == 1
|
|
@@ -1162,6 +1173,8 @@ end
|
|
|
1162
1173
|
stream_id = id.sub(/:([^:]+)$/, ":log-stream:*")
|
|
1163
1174
|
# "arn:aws:logs:us-east-2:accountID:log-group:log_group_name:log-stream:CloudTrail_log_stream_name_prefix*"
|
|
1164
1175
|
statement["Resource"] << stream_id
|
|
1176
|
+
elsif id.match(/:s3:/)
|
|
1177
|
+
statement["Resource"] << id+"/*"
|
|
1165
1178
|
end
|
|
1166
1179
|
else
|
|
1167
1180
|
raise MuError, "Couldn't find a #{target["entity_type"]} named #{target["identifier"]} when generating IAM policy"
|
|
@@ -1180,6 +1193,32 @@ end
|
|
|
1180
1193
|
[]
|
|
1181
1194
|
end
|
|
1182
1195
|
|
|
1196
|
+
# Update a policy, handling deletion of old versions as needed
|
|
1197
|
+
# @param arn [String]:
|
|
1198
|
+
# @param doc [Hash]:
|
|
1199
|
+
# @param credentials [String]:
|
|
1200
|
+
def self.update_policy(arn, doc, credentials: nil)
|
|
1201
|
+
# XXX this is just blindly replacing identical versions, when it should check
|
|
1202
|
+
# and guard
|
|
1203
|
+
begin
|
|
1204
|
+
MU::Cloud::AWS.iam(credentials: credentials).create_policy_version(
|
|
1205
|
+
policy_arn: arn,
|
|
1206
|
+
set_as_default: true,
|
|
1207
|
+
policy_document: JSON.generate(doc)
|
|
1208
|
+
)
|
|
1209
|
+
rescue Aws::IAM::Errors::LimitExceeded
|
|
1210
|
+
delete_version = MU::Cloud::AWS.iam(credentials: credentials).list_policy_versions(
|
|
1211
|
+
policy_arn: arn,
|
|
1212
|
+
).versions.last.version_id
|
|
1213
|
+
MU.log "Purging oldest version (#{delete_version}) of IAM policy #{arn}", MU::NOTICE
|
|
1214
|
+
MU::Cloud::AWS.iam(credentials: credentials).delete_policy_version(
|
|
1215
|
+
policy_arn: arn,
|
|
1216
|
+
version_id: delete_version
|
|
1217
|
+
)
|
|
1218
|
+
retry
|
|
1219
|
+
end
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1183
1222
|
private
|
|
1184
1223
|
|
|
1185
1224
|
# Convert entries from the cloud-neutral @config['policies'] list into
|
|
@@ -1261,28 +1300,6 @@ end
|
|
|
1261
1300
|
MU::Cloud::AWS::Role.update_policy(arn, doc, credentials: @credentials)
|
|
1262
1301
|
end
|
|
1263
1302
|
|
|
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
1303
|
|
|
1287
1304
|
end
|
|
1288
1305
|
end
|