cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Berksfile +16 -54
- data/Berksfile.lock +14 -62
- data/bin/mu-aws-setup +131 -108
- data/bin/mu-configure +311 -74
- data/bin/mu-gcp-setup +84 -62
- data/bin/mu-load-config.rb +46 -2
- data/bin/mu-self-update +11 -9
- data/bin/mu-upload-chef-artifacts +4 -4
- data/{mu.gemspec → cloud-mu.gemspec} +2 -2
- data/cookbooks/awscli/Berksfile +8 -0
- data/cookbooks/mu-activedirectory/Berksfile +11 -0
- data/cookbooks/mu-firewall/Berksfile +9 -0
- data/cookbooks/mu-firewall/metadata.rb +1 -1
- data/cookbooks/mu-glusterfs/Berksfile +10 -0
- data/cookbooks/mu-jenkins/Berksfile +14 -0
- data/cookbooks/mu-master/Berksfile +23 -0
- data/cookbooks/mu-master/attributes/default.rb +1 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +1 -1
- data/cookbooks/mu-master/recipes/init.rb +7 -3
- data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
- data/cookbooks/mu-mongo/Berksfile +10 -0
- data/cookbooks/mu-openvpn/Berksfile +11 -0
- data/cookbooks/mu-php54/Berksfile +13 -0
- data/cookbooks/mu-splunk/Berksfile +10 -0
- data/cookbooks/mu-tools/Berksfile +21 -0
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
- data/cookbooks/mu-utility/Berksfile +9 -0
- data/cookbooks/mu-utility/metadata.rb +2 -1
- data/cookbooks/nagios/Berksfile +7 -4
- data/cookbooks/s3fs/Berksfile +9 -0
- data/environments/dev.json +6 -6
- data/environments/prod.json +6 -6
- data/modules/mu.rb +20 -42
- data/modules/mu/cleanup.rb +102 -100
- data/modules/mu/cloud.rb +90 -28
- data/modules/mu/clouds/aws.rb +449 -218
- data/modules/mu/clouds/aws/alarm.rb +29 -17
- data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
- data/modules/mu/clouds/aws/collection.rb +25 -18
- data/modules/mu/clouds/aws/container_cluster.rb +73 -66
- data/modules/mu/clouds/aws/database.rb +124 -116
- data/modules/mu/clouds/aws/dnszone.rb +27 -20
- data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
- data/modules/mu/clouds/aws/folder.rb +18 -3
- data/modules/mu/clouds/aws/function.rb +77 -23
- data/modules/mu/clouds/aws/group.rb +19 -12
- data/modules/mu/clouds/aws/habitat.rb +153 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
- data/modules/mu/clouds/aws/log.rb +30 -23
- data/modules/mu/clouds/aws/msg_queue.rb +29 -20
- data/modules/mu/clouds/aws/notifier.rb +222 -0
- data/modules/mu/clouds/aws/role.rb +178 -90
- data/modules/mu/clouds/aws/search_domain.rb +40 -24
- data/modules/mu/clouds/aws/server.rb +169 -137
- data/modules/mu/clouds/aws/server_pool.rb +60 -83
- data/modules/mu/clouds/aws/storage_pool.rb +59 -31
- data/modules/mu/clouds/aws/user.rb +36 -27
- data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
- data/modules/mu/clouds/aws/vpc.rb +250 -189
- data/modules/mu/clouds/azure.rb +132 -0
- data/modules/mu/clouds/cloudformation.rb +65 -1
- data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
- data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
- data/modules/mu/clouds/cloudformation/collection.rb +7 -0
- data/modules/mu/clouds/cloudformation/database.rb +7 -0
- data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
- data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
- data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
- data/modules/mu/clouds/cloudformation/log.rb +7 -0
- data/modules/mu/clouds/cloudformation/server.rb +7 -0
- data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
- data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
- data/modules/mu/clouds/google.rb +214 -110
- data/modules/mu/clouds/google/container_cluster.rb +42 -24
- data/modules/mu/clouds/google/database.rb +15 -6
- data/modules/mu/clouds/google/firewall_rule.rb +17 -25
- data/modules/mu/clouds/google/group.rb +13 -5
- data/modules/mu/clouds/google/habitat.rb +105 -0
- data/modules/mu/clouds/google/loadbalancer.rb +28 -20
- data/modules/mu/clouds/google/server.rb +93 -354
- data/modules/mu/clouds/google/server_pool.rb +18 -10
- data/modules/mu/clouds/google/user.rb +22 -14
- data/modules/mu/clouds/google/vpc.rb +97 -69
- data/modules/mu/config.rb +133 -38
- data/modules/mu/config/alarm.rb +25 -0
- data/modules/mu/config/cache_cluster.rb +5 -3
- data/modules/mu/config/cache_cluster.yml +23 -0
- data/modules/mu/config/database.rb +25 -16
- data/modules/mu/config/database.yml +3 -3
- data/modules/mu/config/function.rb +1 -2
- data/modules/mu/config/{project.rb → habitat.rb} +10 -10
- data/modules/mu/config/notifier.rb +85 -0
- data/modules/mu/config/notifier.yml +9 -0
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/search_domain.yml +2 -2
- data/modules/mu/config/server.rb +13 -1
- data/modules/mu/config/server.yml +3 -3
- data/modules/mu/config/server_pool.rb +3 -1
- data/modules/mu/config/storage_pool.rb +3 -1
- data/modules/mu/config/storage_pool.yml +19 -0
- data/modules/mu/config/vpc.rb +70 -8
- data/modules/mu/groomers/chef.rb +2 -3
- data/modules/mu/kittens.rb +500 -122
- data/modules/mu/master.rb +5 -5
- data/modules/mu/mommacat.rb +151 -91
- data/modules/tests/super_complex_bok.yml +12 -0
- data/modules/tests/super_simple_bok.yml +12 -0
- data/spec/mu/clouds/azure_spec.rb +82 -0
- data/spec/spec_helper.rb +105 -0
- metadata +26 -5
- data/modules/mu/clouds/aws/notification.rb +0 -139
- data/modules/mu/config/notification.rb +0 -44
@@ -39,7 +39,7 @@ module MU
|
|
39
39
|
@config['iam_policies'].each { |policy|
|
40
40
|
policy_name = @mu_name+"-"+policy.keys.first.upcase
|
41
41
|
MU.log "Creating IAM policy #{policy_name}"
|
42
|
-
resp = MU::Cloud::AWS.iam.create_policy(
|
42
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).create_policy(
|
43
43
|
policy_name: policy_name,
|
44
44
|
path: "/"+@deploy.deploy_id+"/",
|
45
45
|
policy_document: JSON.generate(policy.values.first),
|
@@ -50,7 +50,7 @@ module MU
|
|
50
50
|
|
51
51
|
if !@config['bare_policies']
|
52
52
|
MU.log "Creating IAM role #{@mu_name}"
|
53
|
-
resp = MU::Cloud::AWS.iam.create_role(
|
53
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).create_role(
|
54
54
|
path: "/"+@deploy.deploy_id+"/",
|
55
55
|
role_name: @mu_name,
|
56
56
|
description: "Generated by Mu",
|
@@ -62,14 +62,13 @@ module MU
|
|
62
62
|
|
63
63
|
# Called automatically by {MU::Deploy#createResources}
|
64
64
|
def groom
|
65
|
-
|
66
65
|
if @config['policies']
|
67
66
|
@config['iam_policies'] ||= []
|
68
67
|
@config['iam_policies'].concat(convert_policies_to_iam)
|
69
68
|
end
|
70
69
|
|
71
70
|
if !@config['bare_policies']
|
72
|
-
resp = MU::Cloud::AWS.iam.get_role(
|
71
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_role(
|
73
72
|
role_name: @mu_name
|
74
73
|
).role
|
75
74
|
ext_tags = resp.tags.map { |t| t.to_h }
|
@@ -78,64 +77,74 @@ module MU
|
|
78
77
|
|
79
78
|
if tag_param.size > 0
|
80
79
|
MU.log "Updating tags on IAM role #{@mu_name}", MU::NOTICE, details: tag_param
|
81
|
-
MU::Cloud::AWS.iam.tag_role(role_name: @mu_name, tags: tag_param)
|
80
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).tag_role(role_name: @mu_name, tags: tag_param)
|
82
81
|
end
|
83
82
|
end
|
84
83
|
|
85
|
-
|
84
|
+
|
85
|
+
if @config['iam_policies'] or @config['import']
|
86
86
|
attached_policies = []
|
87
|
-
configured_policies =
|
88
|
-
|
89
|
-
|
87
|
+
configured_policies = []
|
88
|
+
|
89
|
+
if @config['iam_policies']
|
90
|
+
configured_policies = @config['iam_policies'].map { |p|
|
91
|
+
@mu_name+"-"+p.keys.first.upcase
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
90
95
|
if @config['import']
|
96
|
+
MU.log "Attaching canned #{@config['import'].size > 1 ? "policies" : "policy"} #{@config['import'].join(", ")} to role #{@mu_name}", MU::NOTICE, details: @config['credentials']
|
91
97
|
configured_policies.concat(@config['import'].map { |p| p.gsub(/.*?\/([^:\/]+)$/, '\1') })
|
92
98
|
end
|
93
99
|
|
94
100
|
if !@config['bare_policies']
|
95
|
-
attached_policies = MU::Cloud::AWS.iam.list_attached_role_policies(
|
101
|
+
attached_policies = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
|
96
102
|
role_name: @mu_name
|
97
103
|
).attached_policies
|
98
104
|
attached_policies.each { |a|
|
99
105
|
if !configured_policies.include?(a.policy_name)
|
100
106
|
MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE
|
101
|
-
MU::Cloud::AWS::Role.purgePolicy(a.policy_arn)
|
107
|
+
MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @config['credentials'])
|
102
108
|
end
|
103
109
|
}
|
104
110
|
end
|
105
111
|
|
106
|
-
@config['iam_policies']
|
107
|
-
|
112
|
+
if @config['iam_policies']
|
113
|
+
@config['iam_policies'].each { |policy|
|
114
|
+
policy_name = @mu_name+"-"+policy.keys.first.upcase
|
108
115
|
|
109
|
-
|
110
|
-
|
111
|
-
|
116
|
+
arn = "arn:"+(MU::Cloud::AWS.isGovCloud? ? "aws-us-gov" : "aws")+":iam::"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":policy/#{@deploy.deploy_id}/#{policy_name}"
|
117
|
+
resp = begin
|
118
|
+
desc = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy(policy_arn: arn)
|
112
119
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
version = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy_version(
|
121
|
+
policy_arn: arn,
|
122
|
+
version_id: desc.policy.default_version_id
|
123
|
+
)
|
124
|
+
if version.policy_version.document != URI.encode(JSON.generate(policy.values.first), /[^a-z0-9\-]/i)
|
125
|
+
MU.log "Updating IAM policy #{policy_name}", MU::NOTICE, details: policy.values.first
|
126
|
+
update_policy(arn, policy.values.first)
|
127
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy(policy_arn: arn)
|
128
|
+
else
|
129
|
+
desc
|
130
|
+
end
|
124
131
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
132
|
+
rescue Aws::IAM::Errors::NoSuchEntity => e
|
133
|
+
MU.log "Creating IAM policy #{policy_name}", details: policy.values.first
|
134
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_policy(
|
135
|
+
policy_name: policy_name,
|
136
|
+
path: "/"+@deploy.deploy_id+"/",
|
137
|
+
policy_document: JSON.generate(policy.values.first),
|
138
|
+
description: "Generated from inline policy document for Mu role #{@mu_name}"
|
139
|
+
)
|
140
|
+
end
|
134
141
|
|
135
|
-
|
142
|
+
}
|
143
|
+
end
|
136
144
|
end
|
137
145
|
|
138
|
-
if !@config['bare_policies'] and
|
146
|
+
if !@config['bare_policies'] and
|
147
|
+
(@config['iam_policies'] or @config['import'])
|
139
148
|
bindTo("role", @mu_name)
|
140
149
|
end
|
141
150
|
end
|
@@ -158,22 +167,22 @@ module MU
|
|
158
167
|
def cloud_desc
|
159
168
|
desc = {}
|
160
169
|
if @config['bare_policies']
|
161
|
-
desc["policies"] = MU::Cloud::AWS.iam.list_policies(
|
170
|
+
desc["policies"] = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_policies(
|
162
171
|
path_prefix: "/"+MU.deploy_id+"/"
|
163
172
|
).policies
|
164
173
|
desc["policies"].reject! { |p|
|
165
174
|
!p.policy_name.match(/^#{Regexp.quote(@mu_name)}-/)
|
166
175
|
}
|
167
176
|
else
|
168
|
-
desc["role"] = MU::Cloud::AWS.iam.get_role(
|
177
|
+
desc["role"] = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_role(
|
169
178
|
role_name: @mu_name
|
170
179
|
).role
|
171
180
|
if @config['iam_policies']
|
172
181
|
desc["policies"] = []
|
173
|
-
MU::Cloud::AWS.iam.list_attached_role_policies(
|
182
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
|
174
183
|
role_name: @mu_name
|
175
184
|
).attached_policies.each { |p|
|
176
|
-
desc["policies"] << MU::Cloud::AWS.iam.get_policy(
|
185
|
+
desc["policies"] << MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy(
|
177
186
|
policy_arn: p.policy_arn
|
178
187
|
).policy
|
179
188
|
}
|
@@ -201,7 +210,7 @@ module MU
|
|
201
210
|
my_policies = cloud_desc["policies"]
|
202
211
|
my_policies.each { |p|
|
203
212
|
if p.policy_name == policy
|
204
|
-
old = MU::Cloud::AWS.iam.get_policy_version(
|
213
|
+
old = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy_version(
|
205
214
|
policy_arn: p.arn,
|
206
215
|
version_id: p.default_version_id
|
207
216
|
).policy_version
|
@@ -209,9 +218,17 @@ module MU
|
|
209
218
|
need_update = false
|
210
219
|
doc["Statement"].each { |s|
|
211
220
|
targets.each { |target|
|
212
|
-
|
213
|
-
|
214
|
-
|
221
|
+
targetstr = if target['type']
|
222
|
+
sibling = @deploy.findLitterMate(
|
223
|
+
name: target["identifier"],
|
224
|
+
type: target["type"]
|
225
|
+
)
|
226
|
+
sibling.cloudobj.arn
|
227
|
+
else
|
228
|
+
target['identifier']
|
229
|
+
end
|
230
|
+
if sibling and !s["Resource"].include?(targetstr)
|
231
|
+
s["Resource"] << targetstr
|
215
232
|
need_update = true
|
216
233
|
end
|
217
234
|
}
|
@@ -226,34 +243,34 @@ module MU
|
|
226
243
|
|
227
244
|
# Delete an IAM policy, along with attendant versions and attachments.
|
228
245
|
# @param policy_arn [String]: The ARN of the policy to purge
|
229
|
-
def self.purgePolicy(policy_arn)
|
230
|
-
attachments = MU::Cloud::AWS.iam.list_entities_for_policy(
|
246
|
+
def self.purgePolicy(policy_arn, credentials)
|
247
|
+
attachments = MU::Cloud::AWS.iam(credentials: credentials).list_entities_for_policy(
|
231
248
|
policy_arn: policy_arn
|
232
249
|
)
|
233
250
|
attachments.policy_users.each { |u|
|
234
|
-
MU::Cloud::AWS.iam.detach_user_policy(
|
251
|
+
MU::Cloud::AWS.iam(credentials: credentials).detach_user_policy(
|
235
252
|
user_name: u.user_name,
|
236
253
|
policy_arn: policy_arn
|
237
254
|
)
|
238
255
|
}
|
239
256
|
attachments.policy_groups.each { |g|
|
240
|
-
MU::Cloud::AWS.iam.detach_group_policy(
|
257
|
+
MU::Cloud::AWS.iam(credentials: credentials).detach_group_policy(
|
241
258
|
group_name: g.group_name,
|
242
259
|
policy_arn: policy_arn
|
243
260
|
)
|
244
261
|
}
|
245
262
|
attachments.policy_roles.each { |r|
|
246
|
-
MU::Cloud::AWS.iam.detach_role_policy(
|
263
|
+
MU::Cloud::AWS.iam(credentials: credentials).detach_role_policy(
|
247
264
|
role_name: r.role_name,
|
248
265
|
policy_arn: policy_arn
|
249
266
|
)
|
250
267
|
}
|
251
|
-
versions = MU::Cloud::AWS.iam.list_policy_versions(
|
268
|
+
versions = MU::Cloud::AWS.iam(credentials: credentials).list_policy_versions(
|
252
269
|
policy_arn: policy_arn,
|
253
270
|
).versions
|
254
271
|
versions.each { |v|
|
255
272
|
next if v.is_default_version
|
256
|
-
MU::Cloud::AWS.iam.delete_policy_version(
|
273
|
+
MU::Cloud::AWS.iam(credentials: credentials).delete_policy_version(
|
257
274
|
policy_arn: policy_arn,
|
258
275
|
version_id: v.version_id
|
259
276
|
)
|
@@ -262,51 +279,69 @@ module MU
|
|
262
279
|
# Delete the policy, unless it's one of the global canned ones owned
|
263
280
|
# by AWS
|
264
281
|
if !policy_arn.match(/^arn:aws:iam::aws:/)
|
265
|
-
MU::Cloud::AWS.iam.delete_policy(
|
282
|
+
MU::Cloud::AWS.iam(credentials: credentials).delete_policy(
|
266
283
|
policy_arn: policy_arn
|
267
284
|
)
|
268
285
|
end
|
269
286
|
end
|
270
287
|
|
288
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
289
|
+
# is it localized to a region/zone?
|
290
|
+
# @return [Boolean]
|
291
|
+
def self.isGlobal?
|
292
|
+
true
|
293
|
+
end
|
294
|
+
|
271
295
|
# Remove all roles associated with the currently loaded deployment.
|
272
296
|
# @param noop [Boolean]: If true, will only print what would be done
|
273
297
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
274
298
|
# @param region [String]: The cloud provider region
|
275
299
|
# @return [void]
|
276
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
|
300
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
277
301
|
|
278
|
-
resp = MU::Cloud::AWS.iam.list_policies(
|
302
|
+
resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
|
279
303
|
path_prefix: "/"+MU.deploy_id+"/"
|
280
304
|
)
|
281
305
|
if resp and resp.policies
|
282
306
|
resp.policies.each { |policy|
|
283
307
|
MU.log "Deleting IAM policy /#{MU.deploy_id}/#{policy.policy_name}"
|
284
308
|
if !noop
|
285
|
-
purgePolicy(policy.arn)
|
309
|
+
purgePolicy(policy.arn, credentials)
|
286
310
|
end
|
287
311
|
}
|
288
312
|
end
|
289
313
|
|
290
|
-
resp = MU::Cloud::AWS.iam.list_roles(
|
314
|
+
resp = MU::Cloud::AWS.iam(credentials: credentials).list_roles(
|
291
315
|
path_prefix: "/"+MU.deploy_id+"/"
|
292
316
|
)
|
293
317
|
if resp and resp.roles
|
294
318
|
resp.roles.each { |r|
|
295
319
|
MU.log "Deleting IAM role #{r.role_name}"
|
296
320
|
if !noop
|
321
|
+
# purgePolicy won't touch roles we don't own, so gently detach
|
322
|
+
# those first
|
323
|
+
detachables = MU::Cloud::AWS.iam(credentials: credentials).list_attached_role_policies(
|
324
|
+
role_name: r.role_name
|
325
|
+
).attached_policies
|
326
|
+
detachables.each { |rp|
|
327
|
+
MU::Cloud::AWS.iam(credentials: credentials).detach_role_policy(
|
328
|
+
role_name: r.role_name,
|
329
|
+
policy_arn: rp.policy_arn
|
330
|
+
)
|
331
|
+
}
|
297
332
|
|
298
333
|
begin
|
299
|
-
MU::Cloud::AWS.iam.remove_role_from_instance_profile(
|
334
|
+
MU::Cloud::AWS.iam(credentials: credentials).remove_role_from_instance_profile(
|
300
335
|
instance_profile_name: r.role_name,
|
301
336
|
role_name: r.role_name
|
302
337
|
)
|
303
|
-
MU::Cloud::AWS.iam.delete_instance_profile(instance_profile_name: r.role_name)
|
338
|
+
MU::Cloud::AWS.iam(credentials: credentials).delete_instance_profile(instance_profile_name: r.role_name)
|
304
339
|
rescue Aws::IAM::Errors::ValidationError => e
|
305
340
|
MU.log "Cleaning up IAM role #{r.role_name}: #{e.inspect}", MU::WARN
|
306
341
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
307
342
|
end
|
308
343
|
|
309
|
-
MU::Cloud::AWS.iam.delete_role(
|
344
|
+
MU::Cloud::AWS.iam(credentials: credentials).delete_role(
|
310
345
|
role_name: r.role_name
|
311
346
|
)
|
312
347
|
end
|
@@ -320,7 +355,7 @@ module MU
|
|
320
355
|
# @param region [String]: The cloud provider region.
|
321
356
|
# @param flags [Hash]: Optional flags
|
322
357
|
# @return [OpenStruct]: The cloud provider's complete descriptions of matching user group.
|
323
|
-
def self.find(cloud_id: nil, region: MU.curRegion, flags: {})
|
358
|
+
def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
|
324
359
|
found = nil
|
325
360
|
|
326
361
|
found
|
@@ -331,13 +366,22 @@ module MU
|
|
331
366
|
def bindTo(entitytype, entityname)
|
332
367
|
if entitytype == "instance_profile"
|
333
368
|
begin
|
334
|
-
MU::Cloud::AWS.iam.
|
335
|
-
instance_profile_name: entityname
|
336
|
-
|
337
|
-
|
369
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
|
370
|
+
instance_profile_name: entityname
|
371
|
+
).instance_profile
|
372
|
+
|
373
|
+
if !resp.roles.map { |r| r.role_name}.include?(@mu_name)
|
374
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).add_role_to_instance_profile(
|
375
|
+
instance_profile_name: entityname,
|
376
|
+
role_name: @mu_name
|
377
|
+
)
|
378
|
+
end
|
379
|
+
rescue Exception => e
|
380
|
+
MU.log "Error binding role #{@mu_name} to instance profile #{entityname}: #{e.message}", MU::ERR
|
381
|
+
raise e
|
338
382
|
end
|
339
383
|
elsif ["user", "group", "role"].include?(entitytype)
|
340
|
-
mypolicies = MU::Cloud::AWS.iam.list_policies(
|
384
|
+
mypolicies = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_policies(
|
341
385
|
path_prefix: "/"+@deploy.deploy_id+"/"
|
342
386
|
).policies
|
343
387
|
mypolicies.reject! { |p|
|
@@ -347,47 +391,57 @@ module MU
|
|
347
391
|
if @config['import']
|
348
392
|
@config['import'].each { |policy|
|
349
393
|
if !policy.match(/^arn:/i)
|
350
|
-
|
394
|
+
p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/"+policy
|
395
|
+
end
|
396
|
+
retried = false
|
397
|
+
begin
|
398
|
+
mypolicies << MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy(
|
399
|
+
policy_arn: p_arn
|
400
|
+
).policy
|
401
|
+
rescue Aws::IAM::Errors::NoSuchEntity => e
|
402
|
+
if !retried
|
403
|
+
p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/service-role/"+policy
|
404
|
+
retried = true
|
405
|
+
retry
|
406
|
+
end
|
407
|
+
raise e
|
351
408
|
end
|
352
|
-
mypolicies << MU::Cloud::AWS.iam.get_policy(
|
353
|
-
policy_arn: policy
|
354
|
-
).policy
|
355
409
|
}
|
356
410
|
end
|
357
411
|
|
358
412
|
mypolicies.each { |p|
|
359
413
|
if entitytype == "user"
|
360
|
-
resp = MU::Cloud::AWS.iam.list_attached_user_policies(
|
414
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_user_policies(
|
361
415
|
path_prefix: "/"+@deploy.deploy_id+"/",
|
362
416
|
user_name: entityname
|
363
417
|
)
|
364
418
|
if !resp or !resp.attached_policies.map { |p| p.policy_name }.include?(p.policy_name)
|
365
419
|
MU.log "Attaching IAM policy #{p.policy_name} to user #{entityname}", MU::NOTICE
|
366
|
-
MU::Cloud::AWS.iam.attach_user_policy(
|
420
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_user_policy(
|
367
421
|
policy_arn: p.arn,
|
368
422
|
user_name: entityname
|
369
423
|
)
|
370
424
|
end
|
371
425
|
elsif entitytype == "group"
|
372
|
-
resp = MU::Cloud::AWS.iam.list_attached_group_policies(
|
426
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_group_policies(
|
373
427
|
path_prefix: "/"+@deploy.deploy_id+"/",
|
374
428
|
group_name: entityname
|
375
429
|
)
|
376
430
|
if !resp or !resp.attached_policies.map { |p| p.policy_name }.include?(p.policy_name)
|
377
431
|
MU.log "Attaching policy #{p.policy_name} to group #{entityname}", MU::NOTICE
|
378
|
-
MU::Cloud::AWS.iam.attach_group_policy(
|
432
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_group_policy(
|
379
433
|
policy_arn: p.arn,
|
380
434
|
group_name: entityname
|
381
435
|
)
|
382
436
|
end
|
383
437
|
elsif entitytype == "role"
|
384
|
-
resp = MU::Cloud::AWS.iam.list_attached_role_policies(
|
438
|
+
resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
|
385
439
|
role_name: entityname
|
386
440
|
)
|
387
441
|
|
388
442
|
if !resp or !resp.attached_policies.map { |p| p.policy_name }.include?(p.policy_name)
|
389
443
|
MU.log "Attaching policy #{p.policy_name} to role #{entityname}", MU::NOTICE
|
390
|
-
MU::Cloud::AWS.iam.attach_role_policy(
|
444
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_role_policy(
|
391
445
|
policy_arn: p.arn,
|
392
446
|
role_name: entityname
|
393
447
|
)
|
@@ -407,18 +461,19 @@ module MU
|
|
407
461
|
end
|
408
462
|
|
409
463
|
resp = begin
|
410
|
-
MU
|
464
|
+
MU.log "Creating instance profile #{@mu_name} #{@config['credentials']}"
|
465
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_instance_profile(
|
411
466
|
instance_profile_name: @mu_name
|
412
467
|
)
|
413
468
|
rescue Aws::IAM::Errors::EntityAlreadyExists => e
|
414
|
-
MU::Cloud::AWS.iam.get_instance_profile(
|
469
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
|
415
470
|
instance_profile_name: @mu_name
|
416
471
|
)
|
417
472
|
end
|
418
473
|
|
419
474
|
# make sure it's really there before moving on
|
420
475
|
begin
|
421
|
-
MU::Cloud::AWS.iam.get_instance_profile(instance_profile_name: @mu_name)
|
476
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(instance_profile_name: @mu_name)
|
422
477
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
423
478
|
MU.log e.inspect, MU::WARN
|
424
479
|
sleep 10
|
@@ -469,6 +524,12 @@ module MU
|
|
469
524
|
"description" => "Type of entity which will be permitted to assume this role. See +entity_id+ for details.",
|
470
525
|
"enum" => ["service", "aws", "federated"]+aws_resource_types
|
471
526
|
},
|
527
|
+
"assume_method" => {
|
528
|
+
"type" => "string",
|
529
|
+
"description" => "https://docs.aws.amazon.com/STS/latest/APIReference/API_Operations.html",
|
530
|
+
"enum" => ["basic", "saml", "web"],
|
531
|
+
"default" => "basic"
|
532
|
+
},
|
472
533
|
"entity_id" => {
|
473
534
|
"type" => "string",
|
474
535
|
"description" => "An identifier appropriate for the +entity_type+ which is allowed to assume this role- see details for valid formats.\n
|
@@ -501,15 +562,24 @@ module MU
|
|
501
562
|
|
502
563
|
if role['import']
|
503
564
|
role['import'].each { |policy|
|
504
|
-
if !policy.match(/^arn:/i)
|
505
|
-
|
565
|
+
arn = if !policy.match(/^arn:/i)
|
566
|
+
"arn:"+(MU::Cloud::AWS.isGovCloud?(role["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/"+policy
|
567
|
+
else
|
568
|
+
policy
|
506
569
|
end
|
570
|
+
retried = false
|
507
571
|
begin
|
508
|
-
MU::Cloud::AWS.iam.get_policy(policy_arn:
|
572
|
+
MU::Cloud::AWS.iam(credentials: role['credentials']).get_policy(policy_arn: arn)
|
509
573
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
510
|
-
|
574
|
+
if !retried
|
575
|
+
arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(role["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/service-role/"+policy
|
576
|
+
retried = true
|
577
|
+
retry
|
578
|
+
end
|
579
|
+
MU.log "No such canned AWS IAM policy '#{arn}'", MU::ERR
|
511
580
|
ok = false
|
512
581
|
end
|
582
|
+
policy = arn
|
513
583
|
}
|
514
584
|
end
|
515
585
|
|
@@ -524,6 +594,19 @@ module MU
|
|
524
594
|
ok = false
|
525
595
|
end
|
526
596
|
|
597
|
+
if role['policies']
|
598
|
+
role['policies'].each { |policy|
|
599
|
+
policy['targets'].each { |target|
|
600
|
+
if target['type']
|
601
|
+
role['dependencies'] ||= []
|
602
|
+
role['dependencies'] << {
|
603
|
+
"name" => target['identifier'],
|
604
|
+
"type" => target['type']
|
605
|
+
}
|
606
|
+
end
|
607
|
+
}
|
608
|
+
}
|
609
|
+
end
|
527
610
|
|
528
611
|
ok
|
529
612
|
end
|
@@ -540,7 +623,7 @@ module MU
|
|
540
623
|
"Version" => "2012-10-17",
|
541
624
|
"Statement" => [
|
542
625
|
{
|
543
|
-
"Sid" => policy["name"],
|
626
|
+
"Sid" => policy["name"].gsub(/[^0-9A-Za-z]*/, ""),
|
544
627
|
"Effect" => policy['flag'].capitalize,
|
545
628
|
"Action" => [],
|
546
629
|
"Resource" => []
|
@@ -598,13 +681,18 @@ module MU
|
|
598
681
|
role_policy_doc = {
|
599
682
|
"Version" => "2012-10-17",
|
600
683
|
}
|
601
|
-
|
684
|
+
|
602
685
|
statements = []
|
603
686
|
if @config['can_assume']
|
687
|
+
act_map = {
|
688
|
+
"basic" => "sts:AssumeRole",
|
689
|
+
"saml" => "sts:AssumeRoleWithSAML",
|
690
|
+
"web" => "sts:AssumeRoleWithWebIdentity"
|
691
|
+
}
|
604
692
|
@config['can_assume'].each { |svc|
|
605
693
|
statement = {
|
606
694
|
"Effect" => "Allow",
|
607
|
-
"Action" =>
|
695
|
+
"Action" => act_map[svc['assume_method']],
|
608
696
|
"Principal" => {}
|
609
697
|
}
|
610
698
|
if ["service", "iam", "federated"].include?(svc["entity_type"])
|
@@ -632,17 +720,17 @@ module MU
|
|
632
720
|
# Update a policy, handling deletion of old versions as needed
|
633
721
|
def update_policy(arn, doc)
|
634
722
|
begin
|
635
|
-
MU::Cloud::AWS.iam.create_policy_version(
|
723
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).create_policy_version(
|
636
724
|
policy_arn: arn,
|
637
725
|
set_as_default: true,
|
638
726
|
policy_document: JSON.generate(doc)
|
639
727
|
)
|
640
728
|
rescue Aws::IAM::Errors::LimitExceeded => e
|
641
|
-
delete_version = MU::Cloud::AWS.iam.list_policy_versions(
|
729
|
+
delete_version = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_policy_versions(
|
642
730
|
policy_arn: arn,
|
643
731
|
).versions.last.version_id
|
644
732
|
MU.log "Purging oldest version (#{delete_version}) of IAM policy #{arn}", MU::NOTICE
|
645
|
-
MU::Cloud::AWS.iam.delete_policy_version(
|
733
|
+
MU::Cloud::AWS.iam(credentials: @config['credentials']).delete_policy_version(
|
646
734
|
policy_arn: arn,
|
647
735
|
version_id: delete_version
|
648
736
|
)
|