cloud-mu 3.2.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/ansible/roles/mu-nat/tasks/main.yml +3 -0
  4. data/bin/mu-adopt +12 -1
  5. data/bin/mu-aws-setup +41 -7
  6. data/bin/mu-azure-setup +34 -0
  7. data/bin/mu-configure +214 -119
  8. data/bin/mu-gcp-setup +37 -2
  9. data/bin/mu-load-config.rb +2 -1
  10. data/bin/mu-node-manage +3 -0
  11. data/bin/mu-refresh-ssl +67 -0
  12. data/bin/mu-run-tests +28 -6
  13. data/bin/mu-self-update +30 -10
  14. data/bin/mu-upload-chef-artifacts +30 -26
  15. data/cloud-mu.gemspec +10 -8
  16. data/cookbooks/mu-master/attributes/default.rb +5 -1
  17. data/cookbooks/mu-master/metadata.rb +2 -2
  18. data/cookbooks/mu-master/recipes/default.rb +81 -26
  19. data/cookbooks/mu-master/recipes/init.rb +197 -62
  20. data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
  21. data/cookbooks/mu-master/recipes/vault.rb +78 -77
  22. data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
  23. data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
  24. data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
  25. data/cookbooks/mu-tools/attributes/default.rb +12 -0
  26. data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
  27. data/cookbooks/mu-tools/libraries/helper.rb +98 -4
  28. data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
  29. data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
  30. data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
  31. data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
  32. data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
  33. data/cookbooks/mu-tools/recipes/google_api.rb +7 -0
  34. data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
  35. data/cookbooks/mu-tools/resources/disk.rb +113 -42
  36. data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
  37. data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
  38. data/extras/Gemfile.lock.bootstrap +394 -0
  39. data/extras/bucketstubs/error.html +0 -0
  40. data/extras/bucketstubs/index.html +0 -0
  41. data/extras/clean-stock-amis +11 -3
  42. data/extras/generate-stock-images +6 -3
  43. data/extras/git_rpm/build.sh +20 -0
  44. data/extras/git_rpm/mugit.spec +53 -0
  45. data/extras/image-generators/AWS/centos7.yaml +19 -16
  46. data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
  47. data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
  48. data/extras/image-generators/VMWare/centos8.yaml +15 -0
  49. data/extras/openssl_rpm/build.sh +19 -0
  50. data/extras/openssl_rpm/mussl.spec +46 -0
  51. data/extras/python_rpm/muthon.spec +14 -4
  52. data/extras/ruby_rpm/muby.spec +9 -5
  53. data/extras/sqlite_rpm/build.sh +19 -0
  54. data/extras/sqlite_rpm/muqlite.spec +47 -0
  55. data/install/installer +7 -5
  56. data/modules/mommacat.ru +2 -2
  57. data/modules/mu.rb +14 -7
  58. data/modules/mu/adoption.rb +5 -5
  59. data/modules/mu/cleanup.rb +47 -25
  60. data/modules/mu/cloud.rb +29 -1
  61. data/modules/mu/cloud/dnszone.rb +0 -2
  62. data/modules/mu/cloud/machine_images.rb +1 -1
  63. data/modules/mu/cloud/providers.rb +6 -1
  64. data/modules/mu/cloud/resource_base.rb +16 -7
  65. data/modules/mu/cloud/ssh_sessions.rb +5 -1
  66. data/modules/mu/cloud/wrappers.rb +20 -7
  67. data/modules/mu/config.rb +28 -12
  68. data/modules/mu/config/bucket.rb +31 -2
  69. data/modules/mu/config/cache_cluster.rb +1 -1
  70. data/modules/mu/config/cdn.rb +100 -0
  71. data/modules/mu/config/container_cluster.rb +1 -1
  72. data/modules/mu/config/database.rb +3 -3
  73. data/modules/mu/config/dnszone.rb +4 -3
  74. data/modules/mu/config/endpoint.rb +1 -0
  75. data/modules/mu/config/firewall_rule.rb +1 -1
  76. data/modules/mu/config/function.rb +16 -7
  77. data/modules/mu/config/job.rb +89 -0
  78. data/modules/mu/config/notifier.rb +7 -18
  79. data/modules/mu/config/ref.rb +55 -9
  80. data/modules/mu/config/schema_helpers.rb +12 -3
  81. data/modules/mu/config/server.rb +11 -5
  82. data/modules/mu/config/server_pool.rb +2 -2
  83. data/modules/mu/config/vpc.rb +11 -10
  84. data/modules/mu/defaults/AWS.yaml +106 -106
  85. data/modules/mu/deploy.rb +40 -14
  86. data/modules/mu/groomers/chef.rb +2 -2
  87. data/modules/mu/master.rb +70 -3
  88. data/modules/mu/mommacat.rb +28 -9
  89. data/modules/mu/mommacat/daemon.rb +13 -7
  90. data/modules/mu/mommacat/naming.rb +2 -2
  91. data/modules/mu/mommacat/search.rb +16 -5
  92. data/modules/mu/mommacat/storage.rb +67 -32
  93. data/modules/mu/providers/aws.rb +298 -85
  94. data/modules/mu/providers/aws/alarm.rb +5 -5
  95. data/modules/mu/providers/aws/bucket.rb +284 -50
  96. data/modules/mu/providers/aws/cache_cluster.rb +26 -26
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/providers/aws/collection.rb +16 -16
  99. data/modules/mu/providers/aws/container_cluster.rb +84 -64
  100. data/modules/mu/providers/aws/database.rb +59 -55
  101. data/modules/mu/providers/aws/dnszone.rb +29 -12
  102. data/modules/mu/providers/aws/endpoint.rb +535 -50
  103. data/modules/mu/providers/aws/firewall_rule.rb +32 -26
  104. data/modules/mu/providers/aws/folder.rb +1 -1
  105. data/modules/mu/providers/aws/function.rb +300 -134
  106. data/modules/mu/providers/aws/group.rb +16 -14
  107. data/modules/mu/providers/aws/habitat.rb +4 -4
  108. data/modules/mu/providers/aws/job.rb +469 -0
  109. data/modules/mu/providers/aws/loadbalancer.rb +67 -45
  110. data/modules/mu/providers/aws/log.rb +17 -17
  111. data/modules/mu/providers/aws/msg_queue.rb +22 -13
  112. data/modules/mu/providers/aws/nosqldb.rb +99 -8
  113. data/modules/mu/providers/aws/notifier.rb +137 -65
  114. data/modules/mu/providers/aws/role.rb +119 -83
  115. data/modules/mu/providers/aws/search_domain.rb +166 -30
  116. data/modules/mu/providers/aws/server.rb +209 -118
  117. data/modules/mu/providers/aws/server_pool.rb +95 -130
  118. data/modules/mu/providers/aws/storage_pool.rb +19 -11
  119. data/modules/mu/providers/aws/user.rb +5 -5
  120. data/modules/mu/providers/aws/userdata/linux.erb +5 -4
  121. data/modules/mu/providers/aws/vpc.rb +109 -54
  122. data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
  123. data/modules/mu/providers/azure.rb +78 -12
  124. data/modules/mu/providers/azure/server.rb +20 -4
  125. data/modules/mu/providers/cloudformation/server.rb +1 -1
  126. data/modules/mu/providers/google.rb +21 -5
  127. data/modules/mu/providers/google/bucket.rb +1 -1
  128. data/modules/mu/providers/google/container_cluster.rb +1 -1
  129. data/modules/mu/providers/google/database.rb +1 -1
  130. data/modules/mu/providers/google/firewall_rule.rb +1 -1
  131. data/modules/mu/providers/google/folder.rb +7 -3
  132. data/modules/mu/providers/google/function.rb +66 -31
  133. data/modules/mu/providers/google/group.rb +1 -1
  134. data/modules/mu/providers/google/habitat.rb +1 -1
  135. data/modules/mu/providers/google/loadbalancer.rb +1 -1
  136. data/modules/mu/providers/google/role.rb +6 -3
  137. data/modules/mu/providers/google/server.rb +1 -1
  138. data/modules/mu/providers/google/server_pool.rb +1 -1
  139. data/modules/mu/providers/google/user.rb +1 -1
  140. data/modules/mu/providers/google/vpc.rb +28 -3
  141. data/modules/tests/aws-jobs-functions.yaml +46 -0
  142. data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
  143. data/modules/tests/centos6.yaml +4 -0
  144. data/modules/tests/centos7.yaml +4 -0
  145. data/modules/tests/ecs.yaml +2 -2
  146. data/modules/tests/eks.yaml +1 -1
  147. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  148. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  149. data/modules/tests/k8s.yaml +1 -1
  150. data/modules/tests/microservice_app.yaml +288 -0
  151. data/modules/tests/rds.yaml +5 -5
  152. data/modules/tests/regrooms/rds.yaml +5 -5
  153. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  154. data/modules/tests/super_complex_bok.yml +2 -2
  155. data/modules/tests/super_simple_bok.yml +2 -2
  156. metadata +42 -17
@@ -30,7 +30,7 @@ module MU
30
30
  end
31
31
  end
32
32
 
33
- @mu_name ||= @deploy.getResourceName(@config["name"])
33
+ @mu_name ||= @config['scrub_mu_isms'] ? @config['name'] : @deploy.getResourceName(@config["name"], max_length: 64)
34
34
  end
35
35
 
36
36
  # Called automatically by {MU::Deploy#createResources}
@@ -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
- MU::Cloud::AWS.iam(credentials: @config['credentials']).create_policy(
46
+ MU::Cloud::AWS.iam(credentials: @credentials).create_policy(
47
47
  policy_name: policy_name,
48
48
  path: "/"+@deploy.deploy_id+"/",
49
49
  policy_document: JSON.generate(policy.values.first),
@@ -53,16 +53,18 @@ module MU
53
53
  end
54
54
 
55
55
  if !@config['bare_policies']
56
- MU.log "Creating IAM role #{@mu_name}"
57
56
  @cloud_id = @mu_name
58
57
  path = @config['strip_path'] ? nil : "/"+@deploy.deploy_id+"/"
59
- MU::Cloud::AWS.iam(credentials: @config['credentials']).create_role(
60
- path: path,
61
- role_name: @mu_name,
62
- description: "Generated by Mu",
63
- assume_role_policy_document: gen_assume_role_policy_doc,
64
- tags: get_tag_params
65
- )
58
+ params = {
59
+ :path => path,
60
+ :role_name => @mu_name,
61
+ :description => "Generated by Mu",
62
+ :assume_role_policy_document => gen_assume_role_policy_doc,
63
+ :tags => get_tag_params(@config['scrub_mu_isms'])
64
+ }
65
+
66
+ MU.log "Creating IAM role #{@mu_name} (#{@credentials})", details: params
67
+ MU::Cloud::AWS.iam(credentials: @credentials).create_role(params)
66
68
  end
67
69
  end
68
70
 
@@ -75,7 +77,7 @@ module MU
75
77
  end
76
78
 
77
79
  if !@config['bare_policies']
78
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_role(
80
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).get_role(
79
81
  role_name: @mu_name
80
82
  ).role
81
83
  ext_tags = resp.tags.map { |t| t.to_h }
@@ -84,7 +86,7 @@ module MU
84
86
 
85
87
  if tag_param.size > 0
86
88
  MU.log "Updating tags on IAM role #{@mu_name}", MU::NOTICE, details: tag_param
87
- MU::Cloud::AWS.iam(credentials: @config['credentials']).tag_role(role_name: @mu_name, tags: tag_param)
89
+ MU::Cloud::AWS.iam(credentials: @credentials).tag_role(role_name: @mu_name, tags: tag_param)
88
90
  end
89
91
  end
90
92
 
@@ -92,13 +94,14 @@ module MU
92
94
  configured_policies = []
93
95
 
94
96
  if @config['raw_policies']
97
+ MU.log "Attaching #{@config['raw_policies'].size.to_s} raw #{@config['raw_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
95
98
  configured_policies = @config['raw_policies'].map { |p|
96
99
  @mu_name+"-"+p.keys.first.upcase
97
100
  }
98
101
  end
99
102
 
100
103
  if @config['attachable_policies']
101
- MU.log "Attaching #{@config['attachable_policies'].size.to_s} #{@config['attachable_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
104
+ MU.log "Attaching #{@config['attachable_policies'].size.to_s} external #{@config['attachable_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
102
105
  configured_policies.concat(@config['attachable_policies'].map { |p|
103
106
  id = if p.is_a?(MU::Config::Ref)
104
107
  p.cloud_id
@@ -109,18 +112,17 @@ module MU
109
112
  end
110
113
  id.gsub(/.*?\/([^:\/]+)$/, '\1')
111
114
  })
112
- configured_policies.each { |pol|
113
- }
114
115
  end
115
116
 
117
+ # Purge anything that doesn't belong
116
118
  if !@config['bare_policies']
117
- attached_policies = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
119
+ attached_policies = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
118
120
  role_name: @mu_name
119
121
  ).attached_policies
120
122
  attached_policies.each { |a|
121
123
  if !configured_policies.include?(a.policy_name)
122
- MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE
123
- MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @config['credentials'])
124
+ MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE, details: configured_policies
125
+ MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @credentials)
124
126
  end
125
127
  }
126
128
  end
@@ -153,8 +155,8 @@ module MU
153
155
  policy.values.each { |p|
154
156
  p["Version"] ||= "2012-10-17"
155
157
  }
156
- policy_name = basename+"-"+policy.keys.first.upcase
157
158
 
159
+ policy_name = basename+"-"+policy.keys.first.upcase
158
160
  arn = "arn:"+(MU::Cloud::AWS.isGovCloud? ? "aws-us-gov" : "aws")+":iam::"+MU::Cloud::AWS.credToAcct(credentials)+":policy#{path}/#{policy_name}"
159
161
  resp = begin
160
162
  desc = MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
@@ -164,7 +166,7 @@ module MU
164
166
  version_id: desc.policy.default_version_id
165
167
  )
166
168
 
167
- ext = JSON.parse(URI.decode(version.policy_version.document))
169
+ ext = JSON.parse(CGI.unescape(version.policy_version.document))
168
170
  if ext != policy.values.first
169
171
  # Special exception- we don't want to overwrite extra rules
170
172
  # in MuSecrets policies, because our siblings might have
@@ -184,12 +186,16 @@ module MU
184
186
 
185
187
  rescue Aws::IAM::Errors::NoSuchEntity
186
188
  MU.log "Creating IAM policy #{policy_name}", details: policy.values.first
187
- MU::Cloud::AWS.iam(credentials: credentials).create_policy(
189
+ desc = MU::Cloud::AWS.iam(credentials: credentials).create_policy(
188
190
  policy_name: policy_name,
189
191
  path: path+"/",
190
192
  policy_document: JSON.generate(policy.values.first),
191
193
  description: "Raw policy from #{basename}"
192
194
  )
195
+ MU.retrier([Aws::IAM::Errors::NoSuchEntity], loop_if: Proc.new { desc.nil? }) {
196
+ desc = MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
197
+ }
198
+ desc
193
199
  end
194
200
  arns << resp.policy.arn
195
201
  }
@@ -216,7 +222,23 @@ module MU
216
222
  # populated with one or both depending on what this resource has
217
223
  # defined.
218
224
  def cloud_desc(use_cache: true)
219
- return @cloud_desc_cache if @cloud_desc_cache and use_cache
225
+ require 'aws-sdk-iam'
226
+
227
+ # we might inherit a naive cached description from the base cloud
228
+ # layer; rearrange it to our tastes
229
+ if @cloud_desc_cache.is_a?(::Aws::IAM::Types::Role)
230
+ new_desc = {
231
+ "role" => @cloud_desc_cache
232
+ }
233
+ @cloud_desc_cache = new_desc
234
+ elsif @cloud_desc_cache.is_a?(::Aws::IAM::Types::Policy)
235
+ new_desc = {
236
+ "policies" => [@cloud_desc_cache]
237
+ }
238
+ @cloud_desc_cache = new_desc
239
+ end
240
+
241
+ return @cloud_desc_cache if @cloud_desc_cache and !@cloud_desc_cache.empty? and use_cache
220
242
 
221
243
  @cloud_desc_cache = {}
222
244
  if @config['bare_policies']
@@ -290,8 +312,8 @@ end
290
312
  # Insert a new target entity into an existing policy.
291
313
  # @param policy [String]: The name of the policy to which we're appending, which must already exist as part of this role resource
292
314
  # @param targets [Array<String>]: The target resource. If +target_type+ isn't specified, this should be a fully-resolved ARN.
293
- def injectPolicyTargets(policy, targets)
294
- if !policy.match(/^#{@deploy.deploy_id}/)
315
+ def injectPolicyTargets(policy, targets, attach: false)
316
+ if @deploy and !policy.match(/^#{@deploy.deploy_id}/)
295
317
  policy = @mu_name+"-"+policy.upcase
296
318
  end
297
319
  my_policies = cloud_desc(use_cache: false)["policies"]
@@ -301,19 +323,19 @@ end
301
323
  my_policies.each { |p|
302
324
  if p.policy_name == policy
303
325
  seen_policy = true
304
- old = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy_version(
326
+ old = MU::Cloud::AWS.iam(credentials: @credentials).get_policy_version(
305
327
  policy_arn: p.arn,
306
328
  version_id: p.default_version_id
307
329
  ).policy_version
308
330
 
309
- doc = JSON.parse URI.decode_www_form_component old.document
331
+ doc = JSON.parse CGI.unescape_www_form_component old.document
310
332
  need_update = false
311
333
 
312
334
  doc["Statement"].each { |s|
313
335
  targets.each { |target|
314
336
  target_string = target
315
337
 
316
- if target['type']
338
+ if target['type'] and @deploy
317
339
  sibling = @deploy.findLitterMate(
318
340
  name: target["identifier"],
319
341
  type: target["type"]
@@ -419,14 +441,14 @@ end
419
441
  # @param noop [Boolean]: If true, will only print what would be done
420
442
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
421
443
  # @return [void]
422
- def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
444
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
423
445
 
424
446
  resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
425
- path_prefix: "/"+MU.deploy_id+"/"
447
+ path_prefix: "/"+deploy_id+"/"
426
448
  )
427
449
  if resp and resp.policies
428
450
  resp.policies.each { |policy|
429
- MU.log "Deleting IAM policy /#{MU.deploy_id}/#{policy.policy_name}"
451
+ MU.log "Deleting IAM policy /#{deploy_id}/#{policy.policy_name}"
430
452
  if !noop
431
453
  purgePolicy(policy.arn, credentials)
432
454
  end
@@ -437,19 +459,23 @@ end
437
459
  roles = MU::Cloud::AWS::Role.find(credentials: credentials).values
438
460
  roles.each { |r|
439
461
  next if !r.respond_to?(:role_name)
440
- if r.path.match(/^\/#{Regexp.quote(MU.deploy_id)}/)
462
+ if r.path.match(/^\/#{Regexp.quote(deploy_id)}/)
441
463
  deleteme << r
442
464
  next
443
465
  end
444
466
  # For some dumb reason, the list output that .find gets doesn't
445
467
  # include the tags, so we need to fetch each role individually to
446
468
  # check tags. Hardly seems efficient.
447
- desc = MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
469
+ desc = begin
470
+ MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
471
+ rescue Aws::IAM::Errors::NoSuchEntity
472
+ next
473
+ end
448
474
  if desc.role and desc.role.tags and desc.role.tags
449
475
  master_match = false
450
476
  deploy_match = false
451
477
  desc.role.tags.each { |t|
452
- if t.key == "MU-ID" and t.value == MU.deploy_id
478
+ if t.key == "MU-ID" and t.value == deploy_id
453
479
  deploy_match = true
454
480
  elsif t.key == "MU-MASTER-IP" and t.value == MU.mu_public_ip
455
481
  master_match = true
@@ -516,7 +542,7 @@ end
516
542
 
517
543
  begin
518
544
  # managed policies get fetched by ARN, roles by plain name. Ok!
519
- if args[:cloud_id].match(/^arn:/)
545
+ if args[:cloud_id].match(/^arn:.*?:policy\//)
520
546
  resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).get_policy(
521
547
  policy_arn: args[:cloud_id]
522
548
  )
@@ -525,39 +551,26 @@ end
525
551
  end
526
552
  else
527
553
  resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).get_role(
528
- role_name: args[:cloud_id]
554
+ role_name: args[:cloud_id].sub(/^arn:.*?\/([^:\/]+)$/, '\1') # XXX if it's an ARN, actually parse it and look in the correct account when applicable
529
555
  )
556
+
530
557
  if resp and resp.role
531
- found[args[:cloud_id]] = resp.role
558
+ found[resp.role.role_name] = resp.role
532
559
  end
533
560
  end
534
561
  rescue ::Aws::IAM::Errors::NoSuchEntity
535
562
  end
536
563
 
537
564
  else
538
- marker = nil
539
- begin
540
- resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_roles(
541
- marker: marker
542
- )
543
- break if !resp or !resp.roles
544
- resp.roles.each { |role|
545
- found[role.role_name] = role
546
- }
547
- marker = resp.marker
548
- end while marker
565
+ resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_roles
566
+ resp.roles.each { |role|
567
+ found[role.role_name] = role
568
+ }
549
569
 
550
- begin
551
- resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_policies(
552
- scope: "Local",
553
- marker: marker
554
- )
555
- break if !resp or !resp.policies
556
- resp.policies.each { |pol|
557
- found[pol.arn] = pol
558
- }
559
- marker = resp.marker
560
- end while marker
570
+ resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_policies(scope: "Local")
571
+ resp.policies.each { |pol|
572
+ found[pol.arn] = pol
573
+ }
561
574
  end
562
575
 
563
576
  found
@@ -569,7 +582,7 @@ end
569
582
  def toKitten(**_args)
570
583
  bok = {
571
584
  "cloud" => "AWS",
572
- "credentials" => @config['credentials'],
585
+ "credentials" => @credentials,
573
586
  "cloud_id" => @cloud_id
574
587
  }
575
588
 
@@ -603,7 +616,7 @@ end
603
616
  policy_name: pol.policy_name
604
617
  )
605
618
  if resp and resp.policy_document
606
- JSON.parse(URI.decode(resp.policy_document))
619
+ JSON.parse(CGI.unescape(resp.policy_document))
607
620
  end
608
621
  rescue ::Aws::IAM::Errors::NoSuchEntity, ::Aws::IAM::Errors::ValidationError
609
622
  resp = MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
@@ -613,7 +626,7 @@ end
613
626
  policy_arn: pol.arn,
614
627
  version_id: resp.policy.default_version_id
615
628
  )
616
- JSON.parse(URI.decode(version.policy_version.document))
629
+ JSON.parse(CGI.unescape(version.policy_version.document))
617
630
  end
618
631
  bok["policies"] = MU::Cloud::AWS::Role.doc2MuPolicies(pol.policy_name, doc, bok["policies"])
619
632
  end
@@ -629,7 +642,7 @@ end
629
642
  bok["strip_path"] = true if desc.path == "/"
630
643
 
631
644
  if desc.assume_role_policy_document
632
- assume_doc = JSON.parse(URI.decode(desc.assume_role_policy_document))
645
+ assume_doc = JSON.parse(CGI.unescape(desc.assume_role_policy_document))
633
646
  assume_doc["Statement"].each { |s|
634
647
  bok["can_assume"] ||= []
635
648
  method = if s["Action"] == "sts:AssumeRoleWithWebIdentity"
@@ -762,12 +775,12 @@ end
762
775
  def bindTo(entitytype, entityname)
763
776
  if entitytype == "instance_profile"
764
777
  begin
765
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
778
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(
766
779
  instance_profile_name: entityname
767
780
  ).instance_profile
768
781
 
769
782
  if !resp.roles.map { |r| r.role_name}.include?(@mu_name)
770
- MU::Cloud::AWS.iam(credentials: @config['credentials']).add_role_to_instance_profile(
783
+ MU::Cloud::AWS.iam(credentials: @credentials).add_role_to_instance_profile(
771
784
  instance_profile_name: entityname,
772
785
  role_name: @mu_name
773
786
  )
@@ -777,30 +790,30 @@ end
777
790
  raise e
778
791
  end
779
792
  elsif ["user", "group", "role"].include?(entitytype)
780
- mypolicies = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_policies(
793
+ mypolicies = MU::Cloud::AWS.iam(credentials: @credentials).list_policies(
781
794
  path_prefix: "/"+@deploy.deploy_id+"/"
782
795
  ).policies
783
796
  mypolicies.reject! { |p|
784
- !p.policy_name.match(/^#{Regexp.quote(@mu_name)}-/)
797
+ !p.policy_name.match(/^#{Regexp.quote(@mu_name)}(-|$)/)
785
798
  }
786
799
 
787
800
  if @config['attachable_policies']
788
801
  @config['attachable_policies'].each { |policy_hash|
789
802
  policy = policy_hash["id"]
790
803
  p_arn = if !policy.match(/^arn:/i)
791
- "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/"+policy
804
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":iam::aws:policy/"+policy
792
805
  else
793
806
  policy
794
807
  end
795
808
 
796
809
  subpaths = ["service-role", "aws-service-role", "job-function"]
797
810
  begin
798
- mypolicies << MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy(
811
+ mypolicies << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
799
812
  policy_arn: p_arn
800
813
  ).policy
801
814
  rescue Aws::IAM::Errors::NoSuchEntity => e
802
815
  if subpaths.size > 0
803
- p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+policy
816
+ p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+policy
804
817
  retry
805
818
  end
806
819
  raise e
@@ -808,39 +821,52 @@ end
808
821
  }
809
822
  end
810
823
 
824
+ if @config['raw_policies']
825
+ raw_arns = MU::Cloud::AWS::Role.manageRawPolicies(
826
+ @config['raw_policies'],
827
+ basename: @deploy.getResourceName(@config['name']),
828
+ credentials: @credentials
829
+ )
830
+ raw_arns.each { |p_arn|
831
+ mypolicies << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
832
+ policy_arn: p_arn
833
+ ).policy
834
+ }
835
+ end
836
+
811
837
  mypolicies.each { |p|
812
838
  if entitytype == "user"
813
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_user_policies(
839
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_user_policies(
814
840
  path_prefix: "/"+@deploy.deploy_id+"/",
815
841
  user_name: entityname
816
842
  )
817
843
  if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
818
844
  MU.log "Attaching IAM policy #{p.policy_name} to user #{entityname}", MU::NOTICE
819
- MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_user_policy(
845
+ MU::Cloud::AWS.iam(credentials: @credentials).attach_user_policy(
820
846
  policy_arn: p.arn,
821
847
  user_name: entityname
822
848
  )
823
849
  end
824
850
  elsif entitytype == "group"
825
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_group_policies(
851
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_group_policies(
826
852
  path_prefix: "/"+@deploy.deploy_id+"/",
827
853
  group_name: entityname
828
854
  )
829
855
  if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
830
856
  MU.log "Attaching policy #{p.policy_name} to group #{entityname}", MU::NOTICE
831
- MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_group_policy(
857
+ MU::Cloud::AWS.iam(credentials: @credentials).attach_group_policy(
832
858
  policy_arn: p.arn,
833
859
  group_name: entityname
834
860
  )
835
861
  end
836
862
  elsif entitytype == "role"
837
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
863
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
838
864
  role_name: entityname
839
865
  )
840
866
 
841
867
  if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
842
868
  MU.log "Attaching policy #{p.policy_name} to role #{entityname}", MU::NOTICE
843
- MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_role_policy(
869
+ MU::Cloud::AWS.iam(credentials: @credentials).attach_role_policy(
844
870
  policy_arn: p.arn,
845
871
  role_name: entityname
846
872
  )
@@ -861,19 +887,19 @@ end
861
887
  end
862
888
 
863
889
  resp = begin
864
- MU.log "Creating instance profile #{@mu_name} #{@config['credentials']}"
865
- MU::Cloud::AWS.iam(credentials: @config['credentials']).create_instance_profile(
890
+ MU.log "Creating instance profile #{@mu_name} #{@credentials}"
891
+ MU::Cloud::AWS.iam(credentials: @credentials).create_instance_profile(
866
892
  instance_profile_name: @mu_name
867
893
  )
868
894
  rescue Aws::IAM::Errors::EntityAlreadyExists
869
- MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
895
+ MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(
870
896
  instance_profile_name: @mu_name
871
897
  )
872
898
  end
873
899
 
874
900
  # make sure it's really there before moving on
875
901
  begin
876
- MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(instance_profile_name: @mu_name)
902
+ MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(instance_profile_name: @mu_name)
877
903
  rescue Aws::IAM::Errors::NoSuchEntity => e
878
904
  MU.log e.inspect, MU::WARN
879
905
  sleep 10
@@ -1061,6 +1087,8 @@ end
1061
1087
  role.delete("import")
1062
1088
  end
1063
1089
 
1090
+ role['strip_path'] = true if role['scrub_mu_isms']
1091
+
1064
1092
  # If we're attaching some managed policies, make sure all of the ones
1065
1093
  # that should already exist do indeed exist
1066
1094
  if role['attachable_policies']
@@ -1091,7 +1119,7 @@ end
1091
1119
  role['policies'].each { |policy|
1092
1120
  policy['targets'].each { |target|
1093
1121
  if target['type']
1094
- MU::Config.addDependency(role, target['identifier'], target['type'])
1122
+ MU::Config.addDependency(role, target['identifier'], target['type'], my_phase: "groom")
1095
1123
  end
1096
1124
  }
1097
1125
  }
@@ -1107,13 +1135,14 @@ end
1107
1135
  # @param policies [Array<Hash>]: One or more policy chunks
1108
1136
  # @param deploy_obj [MU::MommaCat]: Deployment object to use when looking up sibling Mu resources
1109
1137
  # @return [Array<Hash>]
1110
- def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false)
1138
+ def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false, version: "2012-10-17", doc_id: nil)
1111
1139
  if policies
1112
1140
  name = nil
1113
1141
  doc = {
1114
- "Version" => "2012-10-17",
1142
+ "Version" => version,
1115
1143
  "Statement" => []
1116
1144
  }
1145
+ doc["Id"] = doc_id if doc_id
1117
1146
  policies.each { |policy|
1118
1147
  policy["flag"] ||= "Allow"
1119
1148
  statement = {
@@ -1154,7 +1183,14 @@ end
1154
1183
  raise MuError, "Couldn't find a #{grantee["type"]} named #{grantee["identifier"]} when generating IAM policy"
1155
1184
  end
1156
1185
  else
1157
- bucket_prefix = grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/) ? "Service" : "AWS"
1186
+ bucket_prefix = if grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/)
1187
+ "Service"
1188
+ elsif grantee["identifier"] =~ /^[a-f0-9]+$/
1189
+ "CanonicalUser"
1190
+ else
1191
+ "AWS"
1192
+ end
1193
+
1158
1194
  if bucket_style
1159
1195
  statement["Principal"] << { bucket_prefix => grantee["identifier"] }
1160
1196
  else